pythodds 0.1.8__py3-none-any.whl
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.
- pythodds-0.1.8.dist-info/METADATA +94 -0
- pythodds-0.1.8.dist-info/RECORD +8 -0
- pythodds-0.1.8.dist-info/WHEEL +4 -0
- pythodds-0.1.8.dist-info/entry_points.txt +2 -0
- pythodds-0.1.8.dist-info/licenses/LICENSE +21 -0
- src/__init__.py +3 -0
- src/utils/__init__.py +13 -0
- src/utils/binomial_distribution.py +105 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pythodds
|
|
3
|
+
Version: 0.1.8
|
|
4
|
+
Summary: Command line utilities for statistics, odds, and probabilities
|
|
5
|
+
Author-email: Nicholas Carsner <nicholascarsner@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: binomial,cli,odds,probability,statistics
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Natural Language :: English
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
18
|
+
Requires-Python: >=3.13
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# pythodds
|
|
22
|
+
|
|
23
|
+
[](https://pypi.org/project/pythodds/)
|
|
24
|
+
[](https://www.python.org/downloads/)
|
|
25
|
+
[](https://github.com/yourusername/pythodds/blob/main/LICENSE)
|
|
26
|
+
|
|
27
|
+
A command-line utility and Python library for calculating statistics, odds, and probabilities.
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **Binomial Distribution**: Calculate PMF, CDF, and survival functions for binomial distributions
|
|
32
|
+
- **Command-line Interface**: Easy-to-use CLI tool (`binom` command)
|
|
33
|
+
- **Pure Python**: No external dependencies
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
Install from PyPI:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install pythodds
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or install from source:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/yourusername/pythodds.git
|
|
47
|
+
cd pythodds
|
|
48
|
+
pip install -e .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
### Command Line
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Calculate binomial distribution probabilities
|
|
57
|
+
binom -n 10 -k 3 -p 0.4
|
|
58
|
+
|
|
59
|
+
# Specify a target and minimum probability threshold
|
|
60
|
+
binom -n 100 -k 30 -p 0.35 --target 40 --min-prob 0.05
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Python Library
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from utils.binomial_distribution import binomial_pmf, binomial_cdf_le, binomial_cdf_ge
|
|
67
|
+
|
|
68
|
+
# P(X = 3) for Binomial(n=10, p=0.4)
|
|
69
|
+
pmf = binomial_pmf(10, 3, 0.4)
|
|
70
|
+
|
|
71
|
+
# P(X <= 3) for Binomial(n=10, p=0.4)
|
|
72
|
+
cdf = binomial_cdf_le(10, 3, 0.4)
|
|
73
|
+
|
|
74
|
+
# P(X >= 3) for Binomial(n=10, p=0.4)
|
|
75
|
+
survival = binomial_cdf_ge(10, 3, 0.4)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Development
|
|
79
|
+
|
|
80
|
+
Clone the repository and install in editable mode:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/yourusername/pythodds.git
|
|
84
|
+
cd pythodds
|
|
85
|
+
pip install -e .
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
91
|
+
|
|
92
|
+
## Author
|
|
93
|
+
|
|
94
|
+
Your Name - [@yourusername](https://github.com/yourusername)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
src/__init__.py,sha256=EEiYwuxYvjris9ZRmHY23fVHPwUyGc0Rlou65MObEoo,104
|
|
2
|
+
src/utils/__init__.py,sha256=O-MGpi86D2C_rw6pPi6OTbRW_CJURT4NReVfrnGQcuw,217
|
|
3
|
+
src/utils/binomial_distribution.py,sha256=V7_zl8P5hry3aP461sTjvmlW6ijaMbBQXIhOCFa4OVQ,3624
|
|
4
|
+
pythodds-0.1.8.dist-info/METADATA,sha256=56G_-v4HjEAt7o9aAf0QzwuooiO41bB6e-pRixWVCG4,2521
|
|
5
|
+
pythodds-0.1.8.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
6
|
+
pythodds-0.1.8.dist-info/entry_points.txt,sha256=YarbxXlq-YQh1g4_CCpFCsOe68BxpKnPIKlksVXuWQs,59
|
|
7
|
+
pythodds-0.1.8.dist-info/licenses/LICENSE,sha256=S9Ffuox47AoTxiwJ0U_qpHi_cE9PCxWAyS2mYi0wbHw,1073
|
|
8
|
+
pythodds-0.1.8.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nicholas Carsner
|
|
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.
|
src/__init__.py
ADDED
src/utils/__init__.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import math
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
"""Command-line utility to compute binomial distribution probabilities.
|
|
10
|
+
|
|
11
|
+
Usage examples:
|
|
12
|
+
python scripts/probability_binom.py -n 10 -k 3 -p 0.4
|
|
13
|
+
python scripts/probability_binom.py -n 100 -k 30 -p 0.35 --target 40 --min-prob 0.05
|
|
14
|
+
|
|
15
|
+
Prints PMF for exactly `k`, CDF for `<= k`, survival `>= k`, and optionally
|
|
16
|
+
the probability of meeting a `target` number of successes and whether that
|
|
17
|
+
probability meets a provided minimum threshold (`--min-prob`).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def binomial_pmf(n: int, k: int, p: float) -> float:
|
|
21
|
+
"""Probability mass function P(X = k) for Binomial(n, p)."""
|
|
22
|
+
if k < 0 or k > n:
|
|
23
|
+
return 0.0
|
|
24
|
+
return math.comb(n, k) * (p ** k) * (1 - p) ** (n - k)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def binomial_cdf_le(n: int, k: int, p: float) -> float:
|
|
28
|
+
"""Cumulative distribution P(X <= k) for Binomial(n, p)."""
|
|
29
|
+
if k < 0:
|
|
30
|
+
return 0.0
|
|
31
|
+
if k >= n:
|
|
32
|
+
return 1.0
|
|
33
|
+
total = 0.0
|
|
34
|
+
for i in range(0, k + 1):
|
|
35
|
+
total += binomial_pmf(n, i, p)
|
|
36
|
+
return total
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def binomial_cdf_ge(n: int, k: int, p: float) -> float:
|
|
40
|
+
"""Survival function P(X >= k) for Binomial(n, p)."""
|
|
41
|
+
if k <= 0:
|
|
42
|
+
return 1.0
|
|
43
|
+
if k > n:
|
|
44
|
+
return 0.0
|
|
45
|
+
return 1.0 - binomial_cdf_le(n, k - 1, p)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace:
|
|
49
|
+
parser = argparse.ArgumentParser(description="Binomial distribution helper")
|
|
50
|
+
parser.add_argument("-n", "--trials", type=int, required=True, help="number of trials (n)")
|
|
51
|
+
parser.add_argument("-k", "--successes", type=int, required=True, help="number of successes (k) to evaluate")
|
|
52
|
+
parser.add_argument("-p", "--p", type=float, required=True, help="historical success probability (0..1)")
|
|
53
|
+
parser.add_argument("--target", type=int, default=None, help="optional target number of successes to evaluate P(X >= target)")
|
|
54
|
+
parser.add_argument("--min-prob", type=float, default=None, help="optional minimum acceptable probability for the target (0..1)")
|
|
55
|
+
parser.add_argument("--precision", type=int, default=6, help="decimal places for printed probabilities")
|
|
56
|
+
return parser.parse_args(argv)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def format_prob(x: float, precision: int) -> str:
|
|
60
|
+
pct = x * 100.0
|
|
61
|
+
fmt = f"{{:.{precision}f}}"
|
|
62
|
+
return f"{fmt.format(x)} ({fmt.format(pct)}%)"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def main(argv: Optional[list[str]] = None) -> int:
|
|
66
|
+
args = parse_args(argv)
|
|
67
|
+
|
|
68
|
+
n = args.trials
|
|
69
|
+
k = args.successes
|
|
70
|
+
p = args.p
|
|
71
|
+
precision = args.precision
|
|
72
|
+
|
|
73
|
+
if not (0.0 <= p <= 1.0):
|
|
74
|
+
print("Error: --p must be between 0 and 1", file=sys.stderr)
|
|
75
|
+
return 2
|
|
76
|
+
if n < 0:
|
|
77
|
+
print("Error: --trials must be non-negative", file=sys.stderr)
|
|
78
|
+
return 2
|
|
79
|
+
|
|
80
|
+
exact = binomial_pmf(n, k, p)
|
|
81
|
+
le = binomial_cdf_le(n, k, p)
|
|
82
|
+
ge = binomial_cdf_ge(n, k, p)
|
|
83
|
+
|
|
84
|
+
print(f"n={n}, k={k}, p={p}")
|
|
85
|
+
print(f"P(X = {k}): {format_prob(exact, precision)}")
|
|
86
|
+
print(f"P(X <= {k}): {format_prob(le, precision)}")
|
|
87
|
+
print(f"P(X >= {k}): {format_prob(ge, precision)}")
|
|
88
|
+
|
|
89
|
+
if args.target is not None:
|
|
90
|
+
target = args.target
|
|
91
|
+
pt = binomial_cdf_ge(n, target, p)
|
|
92
|
+
print(f"P(X >= {target}): {format_prob(pt, precision)}")
|
|
93
|
+
if args.min_prob is not None:
|
|
94
|
+
minp = args.min_prob
|
|
95
|
+
if not (0.0 <= minp <= 1.0):
|
|
96
|
+
print("Error: --min-prob must be between 0 and 1", file=sys.stderr)
|
|
97
|
+
return 2
|
|
98
|
+
meets = pt >= minp
|
|
99
|
+
print(f"Meets minimum {format_prob(minp, precision)}: {meets}")
|
|
100
|
+
|
|
101
|
+
return 0
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
raise SystemExit(main())
|