sdtoolkit 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ramesh-xyz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,247 @@
1
+ Metadata-Version: 2.4
2
+ Name: sdtoolkit
3
+ Version: 0.1.0
4
+ Summary: Dependency-free standard deviation, variance and relative standard deviation for Python
5
+ Author: Ramesh-xyz
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://standarddeviationcalculator.net/
8
+ Project-URL: Documentation, https://ramesh-xyz.github.io/statistics-calculator-toolkit/python.html
9
+ Project-URL: Source, https://github.com/Ramesh-xyz/statistics-calculator-toolkit
10
+ Project-URL: Issues, https://github.com/Ramesh-xyz/statistics-calculator-toolkit/issues
11
+ Project-URL: Changelog, https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/CHANGELOG.md
12
+ Keywords: standard deviation,variance,coefficient of variation,statistics
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # sdtoolkit for Python
22
+
23
+ Part of [statistics-calculator-toolkit](https://github.com/Ramesh-xyz/statistics-calculator-toolkit), which ships the same API for
24
+ [several languages](https://ramesh-xyz.github.io/statistics-calculator-toolkit/).
25
+
26
+ `sdtoolkit` is a small, dependency-free Python package for standard
27
+ deviation, variance, sum of squares, relative standard deviation (RSD) and
28
+ coefficient of variation, with a command-line interface. It uses only the
29
+ standard library and supports Python 3.9 and later.
30
+
31
+ ## Problems it solves
32
+
33
+ - **Picking the wrong formula.** Population and sample versions have
34
+ separate, explicitly named functions, and the CLI prints which divisor it
35
+ used.
36
+ - **Silent precision loss.** The shortcut `Σx² − (Σx)²/n` can return zero or
37
+ even a negative variance for data far from zero. sdtoolkit uses a two-pass
38
+ algorithm with `math.fsum`.
39
+ - **Garbage in, number out.** `None`, `NaN`, infinities, booleans and strings
40
+ raise a clear error instead of producing a plausible-looking result. Missing
41
+ values are never skipped silently.
42
+ - **Undefined RSD.** A zero mean raises an error instead of returning
43
+ infinity or dividing by zero.
44
+
45
+ ## Features
46
+
47
+ | function | returns |
48
+ |---|---|
49
+ | `mean(data)` | arithmetic mean |
50
+ | `sum_of_squares(data)` | SS = Σ(x − x̄)² |
51
+ | `population_variance(data)` | SS / N |
52
+ | `sample_variance(data)` | SS / (n − 1) |
53
+ | `population_stdev(data)` | √(SS / N) |
54
+ | `sample_stdev(data)` | √(SS / (n − 1)) |
55
+ | `relative_std_dev(data, population=False)` | 100 × SD / \|mean\|, in percent |
56
+ | `coefficient_of_variation(data, population=False)` | SD / \|mean\|, as a ratio |
57
+ | `describe(data, population=False)` | `Summary` dataclass with all of the above plus min, max, range |
58
+
59
+ All errors are raised as `sdtoolkit.StatisticsError`, a subclass of
60
+ `ValueError`.
61
+
62
+ ## Install
63
+
64
+ ```
65
+ pip install sdtoolkit
66
+ ```
67
+
68
+ Or from a clone, without installing:
69
+
70
+ ```
71
+ PYTHONPATH=src python -m sdtoolkit 1 2 3
72
+ ```
73
+
74
+ ## Usage
75
+
76
+ ### Python
77
+
78
+ ```python
79
+ >>> import sdtoolkit as sd
80
+ >>> data = [2, 4, 4, 4, 5, 5, 7, 9]
81
+ >>> sd.mean(data)
82
+ 5.0
83
+ >>> sd.sum_of_squares(data)
84
+ 32.0
85
+ >>> sd.population_variance(data), sd.population_stdev(data)
86
+ (4.0, 2.0)
87
+ >>> sd.sample_variance(data), sd.sample_stdev(data)
88
+ (4.571428571428571, 2.138089935299395)
89
+ >>> sd.relative_std_dev(data)
90
+ 42.7617987059879
91
+ >>> sd.coefficient_of_variation(data, population=True)
92
+ 0.4
93
+ >>> sd.describe(data)
94
+ Summary(n=8, mean=5.0, minimum=2.0, maximum=9.0, range=7.0, sum_of_squares=32.0, variance=4.571428571428571, stdev=2.138089935299395, rsd_percent=42.7617987059879, population=False)
95
+ >>> sd.describe(data, population=True).as_dict()["stdev"]
96
+ 2.0
97
+ ```
98
+
99
+ ### Command line
100
+
101
+ ```console
102
+ $ python -m sdtoolkit 2 4 4 4 5 5 7 9
103
+ n 8
104
+ mean 5
105
+ min 2
106
+ max 9
107
+ range 7
108
+ sum of squares 32
109
+ sample variance 4.571428571
110
+ sample std dev 2.138089935
111
+ RSD (%) 42.76179871
112
+ (divisor: n - 1)
113
+ ```
114
+
115
+ ```console
116
+ $ python -m sdtoolkit --population 2 4 4 4 5 5 7 9
117
+ n 8
118
+ mean 5
119
+ min 2
120
+ max 9
121
+ range 7
122
+ sum of squares 32
123
+ population variance 4
124
+ population std dev 2
125
+ RSD (%) 40
126
+ (divisor: N)
127
+ ```
128
+
129
+ Read one column of a CSV file (lines starting with `#` are treated as
130
+ comments):
131
+
132
+ ```console
133
+ $ python -m sdtoolkit --csv examples/sample-datasets.csv --column lab_replicate_mg_l
134
+ n 10
135
+ mean 12.405
136
+ min 12.36
137
+ max 12.45
138
+ range 0.09
139
+ sum of squares 0.00825
140
+ sample variance 0.0009166666667
141
+ sample std dev 0.03027650354
142
+ RSD (%) 0.244066937
143
+ (divisor: n - 1)
144
+ ```
145
+
146
+ Errors go to stderr with exit status 1:
147
+
148
+ ```console
149
+ $ python -m sdtoolkit 1 2 x
150
+ error: argument 3: 'x' is not a number
151
+ $ python -m sdtoolkit 5
152
+ error: sample statistics need at least 2 data points, got 1
153
+ ```
154
+
155
+ After `pip install .` the same CLI is also available as `sdtoolkit`.
156
+
157
+ ## Population vs sample
158
+
159
+ Use the population functions when your data are the entire group you are
160
+ describing. Use the sample functions when your data are drawn from a larger
161
+ group you want to draw conclusions about. The sample formulas divide by
162
+ n − 1 (Bessel's correction), which makes the sample variance an unbiased
163
+ estimate of the population variance, and they need at least two values.
164
+
165
+ `describe`, `relative_std_dev`, `coefficient_of_variation` and the CLI
166
+ default to the sample formulas. Details:
167
+ [Sample vs population](https://ramesh-xyz.github.io/statistics-calculator-toolkit/sample-vs-population.html).
168
+
169
+ ## Formulas
170
+
171
+ ```
172
+ x̄ = Σxᵢ / n
173
+ SS = Σ (xᵢ − x̄)²
174
+ σ² = SS / N σ = √σ²
175
+ s² = SS / (n − 1) s = √s²
176
+ CV = s / |x̄|
177
+ RSD = 100 × s / |x̄| %
178
+ ```
179
+
180
+ A step-by-step walk-through of these formulas is on the
181
+ [standard deviation formula reference](https://standarddeviationcalculator.net/standard-deviation-formula/).
182
+
183
+ Further reading:
184
+
185
+ - [Standard deviation](https://ramesh-xyz.github.io/statistics-calculator-toolkit/standard-deviation.html)
186
+ - [Variance](https://ramesh-xyz.github.io/statistics-calculator-toolkit/variance.html)
187
+ - [Sample vs population](https://ramesh-xyz.github.io/statistics-calculator-toolkit/sample-vs-population.html)
188
+ - [Relative standard deviation](https://ramesh-xyz.github.io/statistics-calculator-toolkit/relative-standard-deviation.html)
189
+ - [Outliers](https://ramesh-xyz.github.io/statistics-calculator-toolkit/outliers.html)
190
+
191
+ ## Example datasets
192
+
193
+ [`examples/sample-datasets.csv`](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/examples/sample-datasets.csv) has three
194
+ small columns: lab replicate readings, exam scores and daily temperatures.
195
+ They are **illustrative values made up for teaching, not real research
196
+ data.** [`examples/worked-examples.md`](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/examples/worked-examples.md) works
197
+ through each one by hand and checks the result with the code.
198
+
199
+ ## Accuracy and edge cases
200
+
201
+ - **Algorithm.** Two passes: the mean, then the squared deviations from it,
202
+ each summed with `math.fsum`. A correction term removes the rounding error
203
+ left in the mean. The test suite compares results with Python's
204
+ `statistics.pvariance`, `variance`, `pstdev` and `stdev` (which use exact
205
+ rational arithmetic) to a relative tolerance of 1e-12, including data
206
+ offset by 10⁹ and 10¹².
207
+ - **Accepted input.** Any iterable of `int`, `float`, `decimal.Decimal` or
208
+ `fractions.Fraction`. Decimals and fractions are converted to `float`, so
209
+ their extra precision is not kept and results are always `float`.
210
+ - **Rejected input.** `bool`, `None`, strings, NaN, ±infinity, complex
211
+ numbers, and integers too large for a float raise `StatisticsError` naming
212
+ the offending item.
213
+ - **Missing values are not skipped.** `None` raises, and an empty CSV cell
214
+ raises with its row number. Remove or impute missing data yourself so the
215
+ choice is visible in your code.
216
+ - **Empty input** raises. **Sample statistics with one value** raise.
217
+ Population variance of one value is 0.
218
+ - **Zero mean.** `relative_std_dev` and `coefficient_of_variation` raise;
219
+ `describe` sets `rsd_percent` to `None`. RSD is only meaningful for
220
+ ratio-scale data; see
221
+ [Relative standard deviation](https://ramesh-xyz.github.io/statistics-calculator-toolkit/relative-standard-deviation.html).
222
+
223
+ ```python
224
+ >>> sd.mean([1, None, 3])
225
+ Traceback (most recent call last):
226
+ ...
227
+ sdtoolkit.core.StatisticsError: item 1: None (missing value); remove or fill it before computing
228
+ >>> sd.sample_stdev([1e9 + 4, 1e9 + 7, 1e9 + 13, 1e9 + 16]) ** 2
229
+ 30.0
230
+ ```
231
+
232
+ ## Tests
233
+
234
+ ```
235
+ PYTHONPATH=src python -m unittest discover -s tests
236
+ ```
237
+
238
+ The suite uses only `unittest`. GitHub Actions runs it on Python 3.9 to 3.13
239
+ ([workflow](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/.github/workflows/test-python.yml)).
240
+
241
+ ## Contributing
242
+
243
+ See [CONTRIBUTING.md](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/CONTRIBUTING.md).
244
+
245
+ ## License
246
+
247
+ MIT. See [LICENSE](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/LICENSE).
@@ -0,0 +1,103 @@
1
+ # statistics-calculator-toolkit
2
+
3
+ Small, dependency-free libraries for the mean, sum of squared deviations,
4
+ population and sample variance, population and sample standard deviation,
5
+ coefficient of variation and relative standard deviation (RSD). Ten
6
+ languages share one API, one algorithm and one set of test vectors.
7
+
8
+ Documentation: <https://ramesh-xyz.github.io/statistics-calculator-toolkit/>
9
+
10
+ ## Problems it solves
11
+
12
+ - **Picking the wrong formula.** Population and sample versions are separate,
13
+ explicitly named functions.
14
+ - **Silent precision loss.** The shortcut `Σx² − (Σx)²/n` can return zero or
15
+ a negative variance for data far from zero. Every implementation here uses
16
+ a corrected two-pass algorithm with compensated summation.
17
+ - **Garbage in, number out.** NaN, infinities and (in dynamic languages)
18
+ `null`, booleans and strings raise an error naming the bad item. Missing
19
+ values are never skipped silently.
20
+ - **Undefined RSD.** A zero mean raises an error instead of returning
21
+ infinity.
22
+
23
+ ## Packages
24
+
25
+ | language | directory | registry | install |
26
+ |---|---|---|---|
27
+ | Python | [`src/sdtoolkit`](src/sdtoolkit) | PyPI | `pip install sdtoolkit` |
28
+ | JavaScript / TypeScript | [`js`](js) | npm | `npm install @rameshxyz/sdtoolkit` |
29
+ | Rust | [`rust`](rust) | crates.io | `cargo add sdtoolkit` |
30
+ | Go | [`go/sdtoolkit`](go/sdtoolkit) | Go modules | `go get github.com/Ramesh-xyz/statistics-calculator-toolkit/go/sdtoolkit` |
31
+ | R | [`r`](r) | CRAN | `install.packages("sdcalc")` |
32
+ | Java / Kotlin | [`java`](java) | Maven Central | `io.github.ramesh-xyz:sdtoolkit` |
33
+ | C# / .NET | [`dotnet`](dotnet) | NuGet | `dotnet add package SdToolkit` |
34
+ | Ruby | [`ruby`](ruby) | RubyGems | `gem install sdtoolkit` |
35
+ | PHP | [`php`](php) | Packagist | `composer require ramesh-xyz/sdtoolkit` |
36
+ | Dart / Flutter | [`dart`](dart) | pub.dev | `dart pub add sdtoolkit` |
37
+
38
+ Each package is released on its own from a git tag (see
39
+ [RELEASING.md](RELEASING.md)); [CHANGELOG.md](CHANGELOG.md) lists what has
40
+ shipped. Each directory's README has usage examples for that language. The
41
+ Python package and its command-line tool are documented in
42
+ [docs/python.md](docs/python.md).
43
+
44
+ ## Example
45
+
46
+ ```python
47
+ >>> import sdtoolkit as sd
48
+ >>> data = [2, 4, 4, 4, 5, 5, 7, 9]
49
+ >>> sd.population_variance(data), sd.population_stdev(data)
50
+ (4.0, 2.0)
51
+ >>> sd.sample_variance(data), sd.sample_stdev(data)
52
+ (4.571428571428571, 2.138089935299395)
53
+ >>> sd.relative_std_dev(data)
54
+ 42.7617987059879
55
+ ```
56
+
57
+ ```console
58
+ $ python -m sdtoolkit --population 2 4 4 4 5 5 7 9
59
+ n 8
60
+ mean 5
61
+ min 2
62
+ max 9
63
+ range 7
64
+ sum of squares 32
65
+ population variance 4
66
+ population std dev 2
67
+ RSD (%) 40
68
+ (divisor: N)
69
+ ```
70
+
71
+ The same numbers come out of every language; [docs/api.md](docs/api.md)
72
+ lists the function names per language, the shared edge-case behaviour and the
73
+ floating-point differences.
74
+
75
+ ## Formulas
76
+
77
+ ```
78
+ x̄ = Σxᵢ / n
79
+ SS = Σ (xᵢ − x̄)²
80
+ σ² = SS / N σ = √σ²
81
+ s² = SS / (n − 1) s = √s²
82
+ CV = s / |x̄|
83
+ RSD = 100 × s / |x̄| %
84
+ ```
85
+
86
+ Guides: [standard deviation](docs/standard-deviation.md),
87
+ [variance](docs/variance.md),
88
+ [sample vs population](docs/sample-vs-population.md),
89
+ [relative standard deviation](docs/relative-standard-deviation.md),
90
+ [outliers](docs/outliers.md). Illustrative datasets and hand-worked examples
91
+ are in [examples/](examples).
92
+
93
+ ## Interactive Standard Deviation Calculator
94
+
95
+ For an interactive online calculator and additional worked examples, visit [StandardDeviationCalculator.net](https://standarddeviationcalculator.net/).
96
+
97
+ ## Contributing
98
+
99
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
100
+
101
+ ## License
102
+
103
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,227 @@
1
+ # sdtoolkit for Python
2
+
3
+ Part of [statistics-calculator-toolkit](https://github.com/Ramesh-xyz/statistics-calculator-toolkit), which ships the same API for
4
+ [several languages](https://ramesh-xyz.github.io/statistics-calculator-toolkit/).
5
+
6
+ `sdtoolkit` is a small, dependency-free Python package for standard
7
+ deviation, variance, sum of squares, relative standard deviation (RSD) and
8
+ coefficient of variation, with a command-line interface. It uses only the
9
+ standard library and supports Python 3.9 and later.
10
+
11
+ ## Problems it solves
12
+
13
+ - **Picking the wrong formula.** Population and sample versions have
14
+ separate, explicitly named functions, and the CLI prints which divisor it
15
+ used.
16
+ - **Silent precision loss.** The shortcut `Σx² − (Σx)²/n` can return zero or
17
+ even a negative variance for data far from zero. sdtoolkit uses a two-pass
18
+ algorithm with `math.fsum`.
19
+ - **Garbage in, number out.** `None`, `NaN`, infinities, booleans and strings
20
+ raise a clear error instead of producing a plausible-looking result. Missing
21
+ values are never skipped silently.
22
+ - **Undefined RSD.** A zero mean raises an error instead of returning
23
+ infinity or dividing by zero.
24
+
25
+ ## Features
26
+
27
+ | function | returns |
28
+ |---|---|
29
+ | `mean(data)` | arithmetic mean |
30
+ | `sum_of_squares(data)` | SS = Σ(x − x̄)² |
31
+ | `population_variance(data)` | SS / N |
32
+ | `sample_variance(data)` | SS / (n − 1) |
33
+ | `population_stdev(data)` | √(SS / N) |
34
+ | `sample_stdev(data)` | √(SS / (n − 1)) |
35
+ | `relative_std_dev(data, population=False)` | 100 × SD / \|mean\|, in percent |
36
+ | `coefficient_of_variation(data, population=False)` | SD / \|mean\|, as a ratio |
37
+ | `describe(data, population=False)` | `Summary` dataclass with all of the above plus min, max, range |
38
+
39
+ All errors are raised as `sdtoolkit.StatisticsError`, a subclass of
40
+ `ValueError`.
41
+
42
+ ## Install
43
+
44
+ ```
45
+ pip install sdtoolkit
46
+ ```
47
+
48
+ Or from a clone, without installing:
49
+
50
+ ```
51
+ PYTHONPATH=src python -m sdtoolkit 1 2 3
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Python
57
+
58
+ ```python
59
+ >>> import sdtoolkit as sd
60
+ >>> data = [2, 4, 4, 4, 5, 5, 7, 9]
61
+ >>> sd.mean(data)
62
+ 5.0
63
+ >>> sd.sum_of_squares(data)
64
+ 32.0
65
+ >>> sd.population_variance(data), sd.population_stdev(data)
66
+ (4.0, 2.0)
67
+ >>> sd.sample_variance(data), sd.sample_stdev(data)
68
+ (4.571428571428571, 2.138089935299395)
69
+ >>> sd.relative_std_dev(data)
70
+ 42.7617987059879
71
+ >>> sd.coefficient_of_variation(data, population=True)
72
+ 0.4
73
+ >>> sd.describe(data)
74
+ Summary(n=8, mean=5.0, minimum=2.0, maximum=9.0, range=7.0, sum_of_squares=32.0, variance=4.571428571428571, stdev=2.138089935299395, rsd_percent=42.7617987059879, population=False)
75
+ >>> sd.describe(data, population=True).as_dict()["stdev"]
76
+ 2.0
77
+ ```
78
+
79
+ ### Command line
80
+
81
+ ```console
82
+ $ python -m sdtoolkit 2 4 4 4 5 5 7 9
83
+ n 8
84
+ mean 5
85
+ min 2
86
+ max 9
87
+ range 7
88
+ sum of squares 32
89
+ sample variance 4.571428571
90
+ sample std dev 2.138089935
91
+ RSD (%) 42.76179871
92
+ (divisor: n - 1)
93
+ ```
94
+
95
+ ```console
96
+ $ python -m sdtoolkit --population 2 4 4 4 5 5 7 9
97
+ n 8
98
+ mean 5
99
+ min 2
100
+ max 9
101
+ range 7
102
+ sum of squares 32
103
+ population variance 4
104
+ population std dev 2
105
+ RSD (%) 40
106
+ (divisor: N)
107
+ ```
108
+
109
+ Read one column of a CSV file (lines starting with `#` are treated as
110
+ comments):
111
+
112
+ ```console
113
+ $ python -m sdtoolkit --csv examples/sample-datasets.csv --column lab_replicate_mg_l
114
+ n 10
115
+ mean 12.405
116
+ min 12.36
117
+ max 12.45
118
+ range 0.09
119
+ sum of squares 0.00825
120
+ sample variance 0.0009166666667
121
+ sample std dev 0.03027650354
122
+ RSD (%) 0.244066937
123
+ (divisor: n - 1)
124
+ ```
125
+
126
+ Errors go to stderr with exit status 1:
127
+
128
+ ```console
129
+ $ python -m sdtoolkit 1 2 x
130
+ error: argument 3: 'x' is not a number
131
+ $ python -m sdtoolkit 5
132
+ error: sample statistics need at least 2 data points, got 1
133
+ ```
134
+
135
+ After `pip install .` the same CLI is also available as `sdtoolkit`.
136
+
137
+ ## Population vs sample
138
+
139
+ Use the population functions when your data are the entire group you are
140
+ describing. Use the sample functions when your data are drawn from a larger
141
+ group you want to draw conclusions about. The sample formulas divide by
142
+ n − 1 (Bessel's correction), which makes the sample variance an unbiased
143
+ estimate of the population variance, and they need at least two values.
144
+
145
+ `describe`, `relative_std_dev`, `coefficient_of_variation` and the CLI
146
+ default to the sample formulas. Details:
147
+ [Sample vs population](https://ramesh-xyz.github.io/statistics-calculator-toolkit/sample-vs-population.html).
148
+
149
+ ## Formulas
150
+
151
+ ```
152
+ x̄ = Σxᵢ / n
153
+ SS = Σ (xᵢ − x̄)²
154
+ σ² = SS / N σ = √σ²
155
+ s² = SS / (n − 1) s = √s²
156
+ CV = s / |x̄|
157
+ RSD = 100 × s / |x̄| %
158
+ ```
159
+
160
+ A step-by-step walk-through of these formulas is on the
161
+ [standard deviation formula reference](https://standarddeviationcalculator.net/standard-deviation-formula/).
162
+
163
+ Further reading:
164
+
165
+ - [Standard deviation](https://ramesh-xyz.github.io/statistics-calculator-toolkit/standard-deviation.html)
166
+ - [Variance](https://ramesh-xyz.github.io/statistics-calculator-toolkit/variance.html)
167
+ - [Sample vs population](https://ramesh-xyz.github.io/statistics-calculator-toolkit/sample-vs-population.html)
168
+ - [Relative standard deviation](https://ramesh-xyz.github.io/statistics-calculator-toolkit/relative-standard-deviation.html)
169
+ - [Outliers](https://ramesh-xyz.github.io/statistics-calculator-toolkit/outliers.html)
170
+
171
+ ## Example datasets
172
+
173
+ [`examples/sample-datasets.csv`](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/examples/sample-datasets.csv) has three
174
+ small columns: lab replicate readings, exam scores and daily temperatures.
175
+ They are **illustrative values made up for teaching, not real research
176
+ data.** [`examples/worked-examples.md`](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/examples/worked-examples.md) works
177
+ through each one by hand and checks the result with the code.
178
+
179
+ ## Accuracy and edge cases
180
+
181
+ - **Algorithm.** Two passes: the mean, then the squared deviations from it,
182
+ each summed with `math.fsum`. A correction term removes the rounding error
183
+ left in the mean. The test suite compares results with Python's
184
+ `statistics.pvariance`, `variance`, `pstdev` and `stdev` (which use exact
185
+ rational arithmetic) to a relative tolerance of 1e-12, including data
186
+ offset by 10⁹ and 10¹².
187
+ - **Accepted input.** Any iterable of `int`, `float`, `decimal.Decimal` or
188
+ `fractions.Fraction`. Decimals and fractions are converted to `float`, so
189
+ their extra precision is not kept and results are always `float`.
190
+ - **Rejected input.** `bool`, `None`, strings, NaN, ±infinity, complex
191
+ numbers, and integers too large for a float raise `StatisticsError` naming
192
+ the offending item.
193
+ - **Missing values are not skipped.** `None` raises, and an empty CSV cell
194
+ raises with its row number. Remove or impute missing data yourself so the
195
+ choice is visible in your code.
196
+ - **Empty input** raises. **Sample statistics with one value** raise.
197
+ Population variance of one value is 0.
198
+ - **Zero mean.** `relative_std_dev` and `coefficient_of_variation` raise;
199
+ `describe` sets `rsd_percent` to `None`. RSD is only meaningful for
200
+ ratio-scale data; see
201
+ [Relative standard deviation](https://ramesh-xyz.github.io/statistics-calculator-toolkit/relative-standard-deviation.html).
202
+
203
+ ```python
204
+ >>> sd.mean([1, None, 3])
205
+ Traceback (most recent call last):
206
+ ...
207
+ sdtoolkit.core.StatisticsError: item 1: None (missing value); remove or fill it before computing
208
+ >>> sd.sample_stdev([1e9 + 4, 1e9 + 7, 1e9 + 13, 1e9 + 16]) ** 2
209
+ 30.0
210
+ ```
211
+
212
+ ## Tests
213
+
214
+ ```
215
+ PYTHONPATH=src python -m unittest discover -s tests
216
+ ```
217
+
218
+ The suite uses only `unittest`. GitHub Actions runs it on Python 3.9 to 3.13
219
+ ([workflow](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/.github/workflows/test-python.yml)).
220
+
221
+ ## Contributing
222
+
223
+ See [CONTRIBUTING.md](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/CONTRIBUTING.md).
224
+
225
+ ## License
226
+
227
+ MIT. See [LICENSE](https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/LICENSE).
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sdtoolkit"
7
+ version = "0.1.0"
8
+ description = "Dependency-free standard deviation, variance and relative standard deviation for Python"
9
+ readme = "docs/python.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Ramesh-xyz" }]
14
+ keywords = ["standard deviation", "variance", "coefficient of variation", "statistics"]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ "Topic :: Scientific/Engineering :: Mathematics",
19
+ ]
20
+
21
+ [project.urls]
22
+ Homepage = "https://standarddeviationcalculator.net/"
23
+ Documentation = "https://ramesh-xyz.github.io/statistics-calculator-toolkit/python.html"
24
+ Source = "https://github.com/Ramesh-xyz/statistics-calculator-toolkit"
25
+ Issues = "https://github.com/Ramesh-xyz/statistics-calculator-toolkit/issues"
26
+ Changelog = "https://github.com/Ramesh-xyz/statistics-calculator-toolkit/blob/main/CHANGELOG.md"
27
+
28
+ [project.scripts]
29
+ sdtoolkit = "sdtoolkit.cli:main"
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,31 @@
1
+ """sdtoolkit: dependency-free standard deviation, variance and RSD."""
2
+
3
+ from .core import (
4
+ StatisticsError,
5
+ Summary,
6
+ coefficient_of_variation,
7
+ describe,
8
+ mean,
9
+ population_stdev,
10
+ population_variance,
11
+ relative_std_dev,
12
+ sample_stdev,
13
+ sample_variance,
14
+ sum_of_squares,
15
+ )
16
+
17
+ __version__ = "0.1.0"
18
+
19
+ __all__ = [
20
+ "StatisticsError",
21
+ "Summary",
22
+ "coefficient_of_variation",
23
+ "describe",
24
+ "mean",
25
+ "population_stdev",
26
+ "population_variance",
27
+ "relative_std_dev",
28
+ "sample_stdev",
29
+ "sample_variance",
30
+ "sum_of_squares",
31
+ ]
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())