Statistics<N extends num>.compute constructor
Statistics<N extends num>.compute (})
Computes a Statistics summary from data
.
alreadySortedData
iftrue
will avoid sorting ofdata
. This allows some usage optimization, do not pass an inconsistent value.computeLowerAndUpper
iftrue
will compute lowerStatistics and upperStatistics.keepData
iftrue
will keep a copy ofdata
atdata
.useBigIntToCompute
iftrue
will force use of BigInt for internal computation to avoid overflow.
Implementation
factory Statistics.compute(Iterable<N> data,
{bool alreadySortedData = false,
bool computeLowerAndUpper = true,
bool keepData = false,
bool useBigIntToCompute = false}) {
var length = data.length;
if (length == 0) {
var statistics = Statistics._empty(data);
if (keepData) {
statistics.data = data.toList();
}
return statistics;
}
if (length == 1) {
var statistics = Statistics._single(data.first);
if (keepData) {
statistics.data = data.toList();
}
return statistics;
}
var listSorted = List<N>.from(data);
if (!alreadySortedData) {
listSorted.sort();
}
var first = listSorted.first;
var min = first;
var max = listSorted.last;
var evenSet = length % 2 == 0;
var medianHighIndex = length ~/ 2;
var medianHigh = listSorted[medianHighIndex];
var medianLow = evenSet ? listSorted[medianHighIndex - 1] : medianHigh;
if (alreadySortedData) {
if (min > max || medianLow > medianHigh) {
throw ArgumentError(
"Inconsistent argument 'alreadySortedData': min:$min > max:$max ; medianLow:$medianLow > medianHigh:$medianHigh");
}
}
num sum;
num squaresSum;
BigInt sumBigInt;
BigInt squaresSumBigInt;
double mean;
double standardDeviation;
if (useBigIntToCompute || max > (maxSafeIntSqrt ~/ length)) {
var firstBigInt = first.toBigInt();
sumBigInt = firstBigInt;
squaresSumBigInt = firstBigInt * firstBigInt;
for (var i = 1; i < length; ++i) {
var n = listSorted[i];
var nBigInt = n.toBigInt();
sumBigInt += nBigInt;
squaresSumBigInt += nBigInt * nBigInt;
}
sum = sumBigInt.toInt();
squaresSum = squaresSumBigInt.toInt();
var lengthBigInt = length.toBigInt();
mean = sumBigInt / lengthBigInt;
standardDeviation = math.sqrt(
((squaresSumBigInt * lengthBigInt) - (sumBigInt * sumBigInt)) /
lengthBigInt) /
math.sqrt(length);
} else {
sum = first;
squaresSum = first * first;
for (var i = 1; i < length; ++i) {
var n = listSorted[i];
sum += n;
squaresSum += n * n;
}
sumBigInt = sum.toBigInt();
squaresSumBigInt = squaresSum.toBigInt();
mean = sum / length;
standardDeviation =
math.sqrt((squaresSum - (sum * (sum / length))) / length);
}
Statistics<N>? lowerStatistics;
Statistics<N>? upperStatistics;
if (computeLowerAndUpper) {
List<N> lower;
List<N> upper;
if (evenSet) {
lower = listSorted.sublist(0, medianHighIndex);
upper = listSorted.sublist(medianHighIndex);
} else {
lower = listSorted.sublist(0, medianHighIndex + 1);
upper = listSorted.sublist(medianHighIndex);
}
lowerStatistics = Statistics.compute(lower,
computeLowerAndUpper: false, keepData: false);
upperStatistics = Statistics.compute(upper,
computeLowerAndUpper: false, keepData: false);
}
var statistics = Statistics<N>(
length,
min,
max,
medianLow: medianLow,
medianHigh: medianHigh,
sum: sum,
squaresSum: squaresSum,
sumBigInt: sumBigInt,
squaresSumBigInt: squaresSumBigInt,
mean: mean,
standardDeviation: standardDeviation,
lowerStatistics: lowerStatistics,
upperStatistics: upperStatistics,
);
if (keepData) {
statistics.data = data.toList();
}
return statistics;
}