YOUSEFUL / DELPHI / COMPONENTS
TAtlasStats
Statistics without a chart: mean, deviation, quantiles, box statistics, histograms, correlation, polynomial fits and smoothing.
Description
Plain statistics with no UI dependency. Every function is a class function ... static, so call them on the class (TAtlasStats.Mean(Values)) without creating an object. The box plot and the analysis helpers use the same functions, so a chart and your own code always agree.
Each function except Sorted validates its input and raises EAtlasPlotError (unit Atlas.PlotAxis) instead of returning NaN: too few values, NaN, infinite values and magnitudes above 1E100 are rejected, as are out-of-range arguments such as a quantile fraction above 1. Inputs are never modified. The functions keep no state and can be called from any thread.
Definitions: quantiles interpolate linearly between closest ranks ("type 7"); the standard deviation is the sample one (n - 1); whiskers end at the most extreme values within 1.5 interquartile ranges of the box; histogram bins are half open except the last; polynomial fits are least squares on arguments scaled to -1..1.
Members
| Member | Kind | What it does |
|---|---|---|
Sorted | method | A sorted copy of Values, ascending; the input is not changed. |
Mean | method | Arithmetic mean. |
StdDev | method | Sample standard deviation (divides by n - 1). |
Quantile | method | The quantile at Fraction (0 to 1) by linear interpolation between closest ranks: position (n - 1) * Fraction in the sorted values (the common "type 7", as in spreadsheet QUARTILE.INC). |
Box | method | Everything a box plot needs: count, minimum, quartiles, median, maximum, mean, whiskers and outliers. |
Histogram | method | Counts Values in Bins equal-width bins from the minimum to the maximum. |
Correlation | method | Pearson's correlation coefficient r, from -1 to 1. |
PolynomialFit | method | Least-squares polynomial of degree 1 to 6 through the points (X[i], Y[i]), with its R squared. |
ExponentialSmoothing | method | Simple exponential smoothing: the first result is the first value, and each later one moves Alpha of the way from the previous result towards the next value. |
Methods
Sorted method
class function Sorted(const Values: TArray<Double>): TArray<Double>; static;A sorted copy of Values, ascending; the input is not changed. Unlike the other functions it does not validate its input (an empty array gives an empty result).
Ordered := TAtlasStats.Sorted([3, 1, 2]); // [1, 2, 3]Mean method
class function Mean(const Values: TArray<Double>): Double; static;Arithmetic mean. Needs at least one value. Computed as a running mean, so values near 1E100 do not overflow.
Value := TAtlasStats.Mean([1, 2, 3, 6]); // 3StdDev method
class function StdDev(const Values: TArray<Double>): Double; static;Sample standard deviation (divides by n - 1). Needs at least two values; 0 when all are equal. Scaled internally so large values do not overflow.
Value := TAtlasStats.StdDev([2, 4, 4, 4, 5, 5, 7, 9]); // Sqrt(32 / 7) = 2.138Quantile method
class function Quantile(const Values: TArray<Double>; const Fraction: Double): Double; static;The quantile at Fraction (0 to 1) by linear interpolation between closest ranks: position (n - 1) * Fraction in the sorted values (the common "type 7", as in spreadsheet QUARTILE.INC). The input need not be sorted. Needs at least one value; a fraction outside 0..1 or NaN raises.
Value := TAtlasStats.Quantile([4, 1, 3, 2], 0.25); // 1.75Box method
class function Box(const Values: TArray<Double>): TAtlasBoxStats; static;Everything a box plot needs: count, minimum, quartiles, median, maximum, mean, whiskers and outliers. See TAtlasBoxStats. Needs at least one value; a single value gives a box of zero size.
Summary := TAtlasStats.Box([1, 2, 3, 4, 5, 6, 7, 8, 9, 40]); // Q1 3.25, median 5.5, Q3 7.75, outlier 40Histogram method
class function Histogram(const Values: TArray<Double>; Bins: Integer = 0): TAtlasHistogram; static;Counts Values in Bins equal-width bins from the minimum to the maximum. Bins 0 chooses Sturges' rule, ceil(log2 n) + 1; otherwise 1 to 10000, and anything outside 0..10000 raises. Bins are half open, [edge, next edge), except the last, which includes the maximum. When all values are equal there is one bin of width one centred on them. See TAtlasHistogram.
Bars := TAtlasStats.Histogram([1, 2, 2, 3, 3, 3, 4, 4, 5], 4); // counts 1, 2, 3, 3Correlation method
class function Correlation(const X, Y: TArray<Double>): Double; static;Pearson's correlation coefficient r, from -1 to 1. Both arrays need the same length, at least two values and some variation; otherwise EAtlasPlotError is raised.
R := TAtlasStats.Correlation([1, 2, 3, 4, 5], [2, 1, 4, 3, 5]); // 0.8PolynomialFit method
class function PolynomialFit(const X, Y: TArray<Double>; Degree: Integer): TAtlasPolynomial; static;Least-squares polynomial of degree 1 to 6 through the points (X[i], Y[i]), with its R squared. Both arrays need the same length and at least Degree + 1 values, and there must be more distinct X values than the degree; otherwise EAtlasPlotError is raised ("A fit needs more distinct arguments than its degree"). The arguments are scaled to -1..1 before fitting, so date values (around 46,000) and other large arguments stay well conditioned. See TAtlasPolynomial.
Fit := TAtlasStats.PolynomialFit([-2, -1, 0, 1, 2], [9, 3, 1, 3, 9], 2);
Value := Fit.Evaluate(3); // 19, since y = 2x² + 1ExponentialSmoothing method
class function ExponentialSmoothing(const Values: TArray<Double>; const Alpha: Double): TArray<Double>; static;Simple exponential smoothing: the first result is the first value, and each later one moves Alpha of the way from the previous result towards the next value. Alpha must be above 0 and at most 1 (1 returns a copy of the input); needs at least one value.
Smooth := TAtlasStats.ExponentialSmoothing([10, 20, 20, 0], 0.5); // 10, 15, 17.5, 8.75Examples
Summarise a sample
Quartiles, whiskers and outliers of a set of response times, with the rejection of bad input.
uses
System.SysUtils, Atlas.PlotAxis, Atlas.PlotStats;
function Describe(const Times: TArray<Double>): string;
var Box: TAtlasBoxStats;
begin
try
Box := TAtlasStats.Box(Times);
Result := Format('n=%d median=%.1f IQR=%.1f..%.1f whiskers=%.1f..%.1f outliers=%d sd=%.2f',
[Box.Count, Box.Median, Box.Q1, Box.Q3, Box.LowWhisker, Box.HighWhisker, Length(Box.Outliers),
TAtlasStats.StdDev(Times)]);
except
on E: EAtlasPlotError do Result := 'cannot describe: ' + E.Message; // e.g. fewer than two values
end;
end;Fit a trend and extrapolate
A quadratic through daily values, evaluated one week beyond the data.
uses
System.Math, Atlas.PlotStats;
function NextWeek(const Days, Sales: TArray<Double>; out RSquared: Double): Double;
var Fit: TAtlasPolynomial;
begin
Fit := TAtlasStats.PolynomialFit(Days, Sales, 2); // raises with fewer than three distinct days
RSquared := Fit.RSquared;
Result := Fit.Evaluate(MaxValue(Days) + 7);
end;Related
TAtlasBoxStats · TAtlasHistogram · TAtlasPolynomial · TAtlasPlotAnalysis · EAtlasPlotError