Skip to content

Releases: simple-statistics/simple-statistics

v7.12.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 01:00
2363d93

Minor Changes

  • e74db06: sampleSkewness accepts a biased flag. Passing true returns the biased coefficient, the population moment ratio m3 / m2^(3/2), which is what R reports and what scipy.stats.skew returns by default. The existing adjusted Fisher-Pearson coefficient stays the default and is unchanged, so this is opt-in. Closes #167.
  • cc052d6: Add scaledRootMeanSquare, an equivalent way of computing the root mean square for values whose squares leave floating point range. rootMeanSquare sums the squares directly, so it returns Infinity above roughly 1e154 and 0 below roughly 1e-162. The new function divides through by the largest magnitude first. rootMeanSquare is unchanged, following the same split as geometricMean and logAverage.
  • 2239688: Add weightedLinearRegression, which fits a line by weighted least squares, the same thing R's lm() does when given a weights argument. linearRegression is the special case where every weight is equal, and it is unchanged. Validation reuses the same helper as the other weighted functions. Closes #48.

Patch Changes

  • d4adf28: Correct the chi-squared critical value at 7 degrees of freedom and an upper tail of 0.99. chiSquaredDistributionTable[7][0.99] carried 1.25, where the exact value is 1.23904 and rounds to 1.24 at the table's two decimal places. At 1.25 the tabulated upper tail is 0.98973 rather than 0.99. chiSquaredGoodnessOfFit compares its statistic against this cell, so a statistic in [1.24, 1.25) was reported as not significant at that level when the correct conclusion is the opposite.
  • b6debf9: Correct gamma for small arguments. Nemes' approximation is asymptotic, dividing its terms by powers of n - 3/4, so the series stops converging once the argument is small. Applied directly it returned 2.8 for gamma(1.01) against a true value of 0.994, and 1.2128 for gamma(1.1) against 0.951. Arguments in (0, 1) were already lifted by a two-step recurrence; that lift now runs generally, raising the argument until the expansion converges. Worst relative error over (0, 30] goes from 1.8 to 1.9e-13, and over [-11, 0) from 0.64 to 2.8e-13, since negative arguments reach the expansion through Euler's reflection formula. The two @example values for gamma(11.5) and gamma(-11.5) recorded the old error and have been updated.
  • cbbae6d: Fix linearRegression losing precision when the x values share a large offset. The one-pass normal equations subtract two large and nearly equal quantities, so cancellation destroys the variance: on a perfect line the slope came back 22% low for x near 1e8, changed sign at 1e9, and was Infinity at 1e10. Timestamps reach this in ordinary use, and with Date.now() as x the slope was 69% wrong. The cross products are now accumulated from deviations about the means, which is what weightedLinearRegression and sampleVariance already do, at the cost of a second pass over the data. weightedLinearRegression documents linearRegression as the special case where every weight is equal; the two disagreed at large x and now agree.
  • 3ca20c8: Correct what mode, modeSorted and modeFast say about ties. All three promised "in the event of a tie, this algorithm will return the most recently seen mode", which none of them does, and they do not agree with each other either. mode sorts its input and modeSorted expects sorted input, so in both cases equal values are adjacent and a tie resolves to the smallest tied value. modeFast walks the input keeping a strict maximum, so a tie resolves to whichever value reaches the highest count first: mode([5, 5, 2, 2]) is 2 while modeFast([5, 5, 2, 2]) is 5. Each docstring now states its own rule and points at the difference, since the three are presented as interchangeable. Tests pin all three behaviours; no behaviour changed.
  • a48dc26: Fix PerceptronModel.train writing through to the caller's feature array. When the feature length did not match the current weight length, train assigned the caller's array to this.weights directly, so the weight-update loop mutated the caller's data in place and the model kept sharing identity with that array. train([1, 2, 3], 0) left the caller holding [0, 0, 0], and a later write to the caller's array silently rewrote the trained weights. train now copies the array, matching the defensive copying already used in shuffle and numericSort.
  • 02907dd: fix: permutationTest now keeps the original sample sizes when permuting unequal-length samples
  • ec2cfc7: Exclude a point from its own cluster when computing its silhouette. a(i), the mean intra-cluster distance, was summed over every member of the point's own cluster including the point itself, whose distance to itself is zero, and divided by the full cluster size rather than one less. That understates a(i) by a factor of (n-1)/n for a cluster of n points, so silhouette and silhouetteMetric returned inflated values for every point in a cluster with more than one member. On the fixture already in the test suite, points [[0.2], [0.4], [0.6], [0.8]] labelled [0, 0, 1, 1] returned [0.8, 2/3, 2/3, 0.8] where the definition gives [0.6, 1/3, 1/3, 0.6], which is what scikit-learn's silhouette_samples returns for the same input. The distortion scales with cluster size, so it is not uniform across clusterings and can affect comparisons between them. b(i), the mean distance to the nearest other cluster, is unchanged: the point is never a member of that group.

v7.11.0

Choose a tag to compare

@github-actions github-actions released this 29 Aug 23:47
a8c348c

Minor Changes

  • 5c54a63: Add normalDistribution(x, mean, standardDeviation, cumulative), the equivalent of spreadsheet NORM.DIST. With cumulative false (the default) it returns the normal probability density, which the library previously had no function for; with cumulative true it returns the cumulative probability via errorFunction, avoiding the two-decimal z rounding and four-decimal table values that bound cumulativeStdNormalProbability's precision.

Patch Changes

  • 5b73a3c: Correct the chi-squared critical value at 25 degrees of freedom and the 0.10 significance level. chiSquaredDistributionTable[25][0.1] carried 34.28 where the exact upper 10% quantile is 34.3816, which rounds to 34.38 at the table's two decimal places. chiSquaredGoodnessOfFit compares its statistic against that cell, so a statistic falling between 34.28 and 34.3816 was reported as significant at the 0.10 level when the correct conclusion is that the null hypothesis cannot be rejected. Checking all 407 entries against exact quantiles found this to be the only cell out of step; the neighbouring rows, 33.20 at 24 degrees of freedom and 35.56 at 26, already matched.
  • e8518fa: Correct six entries at the top of standardNormalTable. The table is built from a Taylor series truncated at 15 terms, which falls short of four-decimal precision above z = 2.9: cumulativeStdNormalProbability(3) returned 0.9986 where the published value is 0.9987, and z = 2.94, 2.96, 2.98, 3.05 and 3.08 were each low by one in the fourth decimal. Thirty terms converge across the whole domain of the table.

v7.10.2

Choose a tag to compare

@github-actions github-actions released this 19 Aug 18:41
7643ea9

Patch Changes

  • 7063073: Make approxEqual's tolerance parameter optional in its type declaration. The implementation defaults it to the library's epsilon (0.0001), but the declaration required all three arguments, so TypeScript rejected the two-argument call the runtime supports. Runtime behavior is unchanged.
  • 62d100a: Correct two JSDoc example values that the implementation does not produce: interquartileRange([0, 1, 2, 3]) returns 1.5 under the type-7 quantile interpolation the library switched to, not the documented 2, and weightedQuantile([1, 2, 3], [1, 1, 2], 0.5) returns 2 — the value its own tests assert — not the documented 3. Documentation-only; runtime behavior is untouched.
  • 08369c8: Declare that jenks can return null. The implementation returns null whenever nClasses is greater than the number of data points — since the function's introduction — but the type declaration promised a plain number[], so TypeScript consumers under strictNullChecks got no warning before dereferencing the result. Runtime behavior is unchanged; only the declaration and docstring now state the null case.
  • f25c2ba: Repair JSDoc that misrenders on the documentation site: quantileRank and quantileRankSorted now document their value parameter (it was missing, and the @returns description read "value value"), jenks's example is tagged @example so it renders as an example instead of leaking into the @returns description, and kMeansCluster's documented example output gets the missing comma that made it invalid JavaScript. Documentation-only; runtime behavior is untouched.
  • 32096eb: Correct the third parameter of the permutationTest type declaration. It was named string and typed string, so TypeScript consumers saw permutationTest(sampleX, sampleY, string?: string, ...) with no indication of which values are accepted. It is now alternative?: "two_side" | "greater" | "less", matching the JSDoc and the three values the implementation accepts before it throws. Runtime behavior is unchanged. The rename is not breaking, since TypeScript binds parameters positionally, but the narrowed type will newly reject a call that passes an arbitrary string — such a call already threw at runtime.
  • f59d6d2: Correct permutationTest's JSDoc to name the alternative value the implementation accepts. The docs described the two-sided test as two_tail and 'two_sided' (default), but passing either throws `alternative` must be either 'two_side', 'greater', or 'less'. — only 'two_side' is accepted. Documentation-only change; runtime behavior is untouched.

v7.10.1

Choose a tag to compare

@github-actions github-actions released this 14 Aug 15:27
0c33928

Patch Changes

  • 894958a: Fix chiSquaredGoodnessOfFit() reporting a fit it never measured. Collapsing a sparse class dropped the last class instead of the one that had just been merged, so observations were discarded and others double counted; an observation past the end of the hypothesized distribution had no expected frequency at all, which made the statistic NaN; and criticalValue < NaN is false, the same answer the function gives for a good fit. Degrees of freedom and significance levels the table does not cover now raise a descriptive error instead of a TypeError or a silent false.
  • a078231: Declare that PerceptronModel#predict and PerceptronModel#train can return null. predict returns null when the feature array's length differs from what the model was trained on, and train returns null when the label is not 0 or 1 — both since their introduction — but the type declarations promised plain number and PerceptronModel, so TypeScript consumers under strictNullChecks got no warning before dereferencing the result. Runtime behavior is unchanged; only the declarations and docstrings now state the null cases.

v7.10.0

Choose a tag to compare

@github-actions github-actions released this 09 Aug 19:57
8449cf5

Minor Changes

  • 2149cff: Fix poissonDistribution() and binomialDistribution() returning a truncated table ending in Infinity or NaN. Both built each cell from a power and a factorial (or a binomial coefficient) that leave floating-point range long before their product does, so the cumulative-probability stopping rule was satisfied by a non-finite sum instead of by the distribution: poissonDistribution(200) returned 135 cells covering 0.000045% of the distribution, and binomialDistribution(10000, 0.5) returned 135 cells covering none of it. Cells are now taken through gammaln, and a table that cannot be completed returns undefined rather than a partial one.

    NOTE: this is tagged as a minor change but you should be aware that it does change behavior
    for binomialDistribution. For most users this won't be a big deal.

    1. Both functions now return undefined in cases where they used to return an array of non-finite cells. binomialDistribution(5, NaN) returned [NaN] and now returns undefined. Their TypeScript declarations widen to number[] | undefined.
    2. Evaluating cells through logarithms costs a precision where the old product form was exact: binomialDistribution(2, 0.5) returns [0.25000000000000006, 0.5000000000000006, 0.25000000000000006] rather than [0.25, 0.5, 0.25]. This precision loss is small but if you're comparing exact results, it may require updates or rounding.

Patch Changes

  • 13530b2: Fix wilcoxon rank-sum test behavior

    This fixes a bug in which the tie averaging in wilcoxonRankSum was
    incorrect and would return an unrelated position.

  • 0779f22: Fix sampleRankCorrelation returning different results for the same data depending on the order the pairs are listed in. Tied values were given distinct consecutive ranks broken by original array position, rather than sharing the average of the ranks they span as Spearman's rho requires. Reordering rows could change the magnitude and even the sign of the result. Tied values now receive midranks, so the correlation depends only on the paired data. As a consequence an input with no rank variance — every value tied — now correctly returns NaN instead of reporting near-perfect correlation. Results for inputs with no ties are unchanged.

v7.9.3

Choose a tag to compare

@github-actions github-actions released this 03 Jul 16:31
f9d368f

Patch Changes

  • 2a98671: Mark the package as "type": "module" and rename the CommonJS bundle to dist/simple-statistics.cjs. Consumers resolve through the exports map, so both import "simple-statistics" and require("simple-statistics") keep working unchanged — only the internal CJS bundle path moved. (Code that hard-coded the deep path simple-statistics/dist/simple-statistics.js, bypassing the package entry points, should switch to the package name or the .cjs path.)

v7.9.2

Choose a tag to compare

@github-actions github-actions released this 30 Jun 14:07
5715425

Patch Changes

  • d571a60: Fix quantile() bug when an array was provided as the second argument

    Thanks Alexander Kireyev for the identification
    and fix.

v7.9.1

Choose a tag to compare

@github-actions github-actions released this 26 Jun 13:52
17ba2f9

Patch Changes

  • 9c1bb2f: fix: gamma() no longer infinitely recurses for 0 < n < 1

v7.9.0

Choose a tag to compare

@github-actions github-actions released this 04 Jun 15:00
b963ea8

Minor Changes

  • b7b2053: Add weighted mean, weighted variance, weighted standard deviation, and weighted quantile.

v7.8.9

Choose a tag to compare

@github-actions github-actions released this 10 Mar 14:27
91a309a

Patch Changes

  • 2daf714: Adopt changesets as a release mechanism
  • 8bb4ae7: Quantiles were incorrect when they were interpolating between two elements in the input. They now match type=7, which is the default in numpy.percentile and R's quantile.

All notable changes to this project will be documented in this file. See standard-version for commit guidelines.

7.8.8 (2025-03-07)

Bug Fixes

  • Add missing types from types bundle file (#756) (20d7e44)

7.8.7 (2024-10-16)

7.8.6 (2024-10-16)

7.8.5 (2024-08-27)

7.8.4 (2024-08-15)

7.8.3 (2023-02-13)

7.8.2 (2023-01-15)

7.8.1 (2023-01-15)

Bug Fixes