betaMixPy 0.1.4__tar.gz → 0.2.1__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.
- betamixpy-0.2.1/PKG-INFO +178 -0
- betamixpy-0.2.1/README.md +152 -0
- betamixpy-0.2.1/betaMixPy/__init__.py +3 -0
- betamixpy-0.2.1/betaMixPy/betaMixPy.py +1282 -0
- betamixpy-0.2.1/betaMixPy.egg-info/PKG-INFO +178 -0
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/betaMixPy.egg-info/SOURCES.txt +2 -1
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/betaMixPy.egg-info/requires.txt +0 -2
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/setup.py +8 -3
- betamixpy-0.2.1/tests/test_betaMixPy.py +479 -0
- betaMixPy-0.1.4/PKG-INFO +0 -28
- betaMixPy-0.1.4/README.md +0 -15
- betaMixPy-0.1.4/betaMixPy/__init__.py +0 -1
- betaMixPy-0.1.4/betaMixPy/betaMixPy.py +0 -388
- betaMixPy-0.1.4/betaMixPy.egg-info/PKG-INFO +0 -28
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/LICENSE +0 -0
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/betaMixPy.egg-info/dependency_links.txt +0 -0
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/betaMixPy.egg-info/top_level.txt +0 -0
- {betaMixPy-0.1.4 → betamixpy-0.2.1}/setup.cfg +0 -0
betamixpy-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: betaMixPy
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: A Python package to find strong correlations among P variables, each with N observations.
|
|
5
|
+
Home-page: https://pypi.org/project/betaMixPy/
|
|
6
|
+
Author: Haim Bar
|
|
7
|
+
Author-email: haim.bar@uconn.edu
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: matplotlib
|
|
14
|
+
Requires-Dist: pandas
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: scipy
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: author-email
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
# betaMixPy
|
|
28
|
+
|
|
29
|
+
Python implementation of the **betaMix** method for detecting edges (significant pairwise associations) in gene co-expression and other multivariate networks.
|
|
30
|
+
|
|
31
|
+
The method is built on the result of Frankl & Maehara (1990): two random vectors in a high-dimensional space are nearly orthogonal with high probability. Pairwise correlations equal the cosine of the angle between column vectors, so the statistic $z_j = 1 - r_{ij}^2 \in (0,1]$ follows a $\mathrm{Beta}((N-1)/2,\,1/2)$ null distribution. An EM algorithm fits a two-component Beta mixture to all $P(P-1)/2$ pairs simultaneously, and a threshold is derived that simultaneously controls a frequentist (Type I error) and a Bayesian (posterior probability) false-positive rate.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
pip install betaMixPy
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import pandas as pd
|
|
43
|
+
import betaMixPy as bx
|
|
44
|
+
|
|
45
|
+
# M is N×P: samples in rows, variables (genes/metabolites) in columns
|
|
46
|
+
M = pd.read_csv("my_data.csv", index_col=0)
|
|
47
|
+
res = bx.betaMix(M, ppr=0.01, ind=True) # fit the mixture model
|
|
48
|
+
|
|
49
|
+
bx.shortSummary(res) # parameter estimates + edge count
|
|
50
|
+
bx.assessFit(res) # 2×2 diagnostic panel
|
|
51
|
+
|
|
52
|
+
adjM = bx.getAdjMat(res) # P×P adjacency matrix
|
|
53
|
+
clust = bx.graphComponents(adjM, minCtr=2) # disjoint clusters
|
|
54
|
+
bx.plotBitmapCC(adjM, clust) # bitmap of adjacency
|
|
55
|
+
bx.plotCluster(adjM, 1, clust, labels=True) # network plot of cluster 1
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Input convention
|
|
59
|
+
|
|
60
|
+
`betaMix()` expects **M as N×P** — N samples in rows, P variables in columns — matching numpy's `corrcoef(M, rowvar=False)` and the R `betaMix` package.
|
|
61
|
+
|
|
62
|
+
> **Upgrading from ≤ 0.1.4?** Remove any `.T` transpose and update code that unpacked the previous tuple return value. See [NEWS.md](NEWS.md) for the full list of breaking changes.
|
|
63
|
+
|
|
64
|
+
## Key functions
|
|
65
|
+
|
|
66
|
+
### Fitting and diagnostics
|
|
67
|
+
|
|
68
|
+
| Function | Description |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `betaMix(M, ...)` | Fit the two-component Beta mixture; returns a `dict` |
|
|
71
|
+
| `shortSummary(res)` | Print parameter estimates and edge count |
|
|
72
|
+
| `assessFit(res)` | 2×2 panel: mixture histogram, null Q-Q, non-null Q-Q, ROC |
|
|
73
|
+
| `plotFittedBetaMix(res)` | Fitted mixture density on log scale |
|
|
74
|
+
| `plotROC(res)` | Model-based ROC; returns AUC and Youden-index threshold |
|
|
75
|
+
| `plotNonNullDensity(res)` | Kernel density of non-null z_j values |
|
|
76
|
+
|
|
77
|
+
### Network analysis
|
|
78
|
+
|
|
79
|
+
| Function | Description |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `getAdjMat(res, ...)` | Build P×P adjacency matrix; `signed=True` for −1/0/1 |
|
|
82
|
+
| `graphComponents(A, ...)` | Disjoint clusters via centrality-based assignment |
|
|
83
|
+
| `sphericalCaps(A, ...)` | Hub-and-spoke clustering (greedy, degree-ordered) |
|
|
84
|
+
| `greedyBasis(A, strategy, ...)` | **Overlapping communities** via maximal independent set |
|
|
85
|
+
| `summarizeClusters(ci)` | Five-number summary per cluster |
|
|
86
|
+
| `summarizeBasis(bi)` | Summary for a `greedyBasis()` result |
|
|
87
|
+
| `collapsedGraph(res, ci)` | Adjacency matrix reduced to cluster centres |
|
|
88
|
+
| `shortestPathDistance(A, numSteps)` | Multi-hop distances in the network |
|
|
89
|
+
| `clusteringCoef(A)` | Vectorised clustering coefficients |
|
|
90
|
+
|
|
91
|
+
### Visualisation
|
|
92
|
+
|
|
93
|
+
| Function | Description |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `plotBitmapCC(A, ...)` | Bitmap heatmap of adjacency, coloured by cluster |
|
|
96
|
+
| `plotCluster(A, n, ci, ...)` | Force-directed network plot of cluster `n` |
|
|
97
|
+
| `plotDegCC(res, ci)` | Degree vs clustering coefficient scatter |
|
|
98
|
+
|
|
99
|
+
## `betaMix()` parameters
|
|
100
|
+
|
|
101
|
+
| Parameter | Default | Meaning |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `M` | required | N×P DataFrame or array |
|
|
104
|
+
| `ind` | `True` | Independent samples? `False` estimates an effective sample size ν |
|
|
105
|
+
| `maxalpha` | `1e-4` | Per-pair frequentist Type I error bound (use `1e-6` for P > 1000) |
|
|
106
|
+
| `ppr` | `0.05` | Posterior null probability threshold for calling an edge |
|
|
107
|
+
| `method` | `"pearson"` | `"pearson"` or `"spearman"` |
|
|
108
|
+
| `subsamplesize` | `50000` | Pairs subsampled for EM; ≥ 20 000 required (ignored if smaller) |
|
|
109
|
+
| `bmax` | `0.999` | Upper bound of non-null support |
|
|
110
|
+
| `seed` | `912469` | Random seed for subsampling reproducibility |
|
|
111
|
+
| `msg` | `False` | Print EM iteration progress |
|
|
112
|
+
|
|
113
|
+
**Returns** a dict with: `angleMat`, `z_j`, `m0`, `p0`, `ahat`, `bhat`, `etahat`, `ppthr`, `nodes`, `edges`, `bmax`, `N`, `cnt`, `method`.
|
|
114
|
+
|
|
115
|
+
## Overlapping communities with `greedyBasis()`
|
|
116
|
+
|
|
117
|
+
Unlike `graphComponents` (disjoint) and `sphericalCaps` (hub-centric), `greedyBasis` finds a **maximal independent set (MIS)**: a set of mutually non-adjacent representative nodes. Each remaining node is then assigned to every community whose centre it is adjacent to, giving overlapping membership.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
adjM = bx.getAdjMat(res)
|
|
121
|
+
basis = bx.greedyBasis(adjM, strategy="min_degree", labels=M.columns)
|
|
122
|
+
# columns: node, isBasis, basisOrder, degree, cc, nCovered, nCommunities, communities
|
|
123
|
+
|
|
124
|
+
bx.summarizeBasis(basis)
|
|
125
|
+
|
|
126
|
+
# Nodes in multiple communities simultaneously:
|
|
127
|
+
bridges = basis[basis["nCommunities"] > 1]
|
|
128
|
+
|
|
129
|
+
# Members of the community centred on node 5:
|
|
130
|
+
community5 = basis[basis["communities"].apply(lambda c: 5 in c)]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Two strategies:
|
|
134
|
+
|
|
135
|
+
| Strategy | Selects first | Basis size | Community size | Overlap |
|
|
136
|
+
|---|---|---|---|---|
|
|
137
|
+
| `"min_degree"` (default) | Least-connected node | Larger | Smaller | Higher |
|
|
138
|
+
| `"max_degree"` | Most-connected hub | Smaller | Larger | Lower |
|
|
139
|
+
|
|
140
|
+
**Guaranteed properties**: no two basis nodes share an edge (independence); every non-basis node has at least one basis neighbour (maximality).
|
|
141
|
+
|
|
142
|
+
## Choosing the right clustering function
|
|
143
|
+
|
|
144
|
+
| | `graphComponents` | `sphericalCaps` | `greedyBasis` |
|
|
145
|
+
|---|---|---|---|
|
|
146
|
+
| Membership | Disjoint | Overlapping | Overlapping |
|
|
147
|
+
| Basis nodes adjacent? | Yes | Yes | **No** (independent set) |
|
|
148
|
+
| Selection criterion | Max degree × cc | Max degree | Min or max degree |
|
|
149
|
+
| Best for | General clusters | Hub-spoke networks | Non-redundant representatives |
|
|
150
|
+
|
|
151
|
+
## What's new in 0.2.x
|
|
152
|
+
|
|
153
|
+
See [NEWS.md](NEWS.md) for the full changelog. Highlights:
|
|
154
|
+
|
|
155
|
+
- **0.2.1**: `getAdjMat` edge count now matches `betaMix()`; fixed a
|
|
156
|
+
`plotFittedBetaMix` crash; unused dependencies removed; full test suite
|
|
157
|
+
|
|
158
|
+
- **`greedyBasis()`** — overlapping community detection via MIS
|
|
159
|
+
- **Input convention**: M is now N×P (remove any `.T` in existing code)
|
|
160
|
+
- **`betaMix()` returns a `dict`** instead of a tuple
|
|
161
|
+
- **`method="spearman"`** for rank-based correlation
|
|
162
|
+
- **`assessFit()`**, **`plotROC()`**, **`plotNonNullDensity()`** — new diagnostics
|
|
163
|
+
- **Vectorised `clusteringCoef()`** — approximately 10–80× faster
|
|
164
|
+
- Analytic Jacobian for MLE; `brentq` for eta estimation — matching R's solvers
|
|
165
|
+
- Python is approximately 3× faster than R on large benchmark datasets
|
|
166
|
+
|
|
167
|
+
## See also
|
|
168
|
+
|
|
169
|
+
- R package: [github.com/haimbar/betaMix](https://github.com/haimbar/betaMix)
|
|
170
|
+
- LLM-friendly function reference: [llms.txt](llms.txt)
|
|
171
|
+
- Version history: [NEWS.md](NEWS.md)
|
|
172
|
+
- Additional examples and data: [code/](code/), [data/](data/), [doc/](doc/)
|
|
173
|
+
|
|
174
|
+
## References
|
|
175
|
+
|
|
176
|
+
Bar, H. & Wells, M. T. (2023). On graphical models and convex geometry. *Computational Statistics & Data Analysis*, 187, 107800. https://doi.org/10.1016/j.csda.2023.107800
|
|
177
|
+
|
|
178
|
+
Frankl, P. & Maehara, H. (1990). Some geometric applications of the beta distribution. *Annals of the Institute of Statistical Mathematics*, 42(3), 463–474.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# betaMixPy
|
|
2
|
+
|
|
3
|
+
Python implementation of the **betaMix** method for detecting edges (significant pairwise associations) in gene co-expression and other multivariate networks.
|
|
4
|
+
|
|
5
|
+
The method is built on the result of Frankl & Maehara (1990): two random vectors in a high-dimensional space are nearly orthogonal with high probability. Pairwise correlations equal the cosine of the angle between column vectors, so the statistic $z_j = 1 - r_{ij}^2 \in (0,1]$ follows a $\mathrm{Beta}((N-1)/2,\,1/2)$ null distribution. An EM algorithm fits a two-component Beta mixture to all $P(P-1)/2$ pairs simultaneously, and a threshold is derived that simultaneously controls a frequentist (Type I error) and a Bayesian (posterior probability) false-positive rate.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pip install betaMixPy
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import pandas as pd
|
|
17
|
+
import betaMixPy as bx
|
|
18
|
+
|
|
19
|
+
# M is N×P: samples in rows, variables (genes/metabolites) in columns
|
|
20
|
+
M = pd.read_csv("my_data.csv", index_col=0)
|
|
21
|
+
res = bx.betaMix(M, ppr=0.01, ind=True) # fit the mixture model
|
|
22
|
+
|
|
23
|
+
bx.shortSummary(res) # parameter estimates + edge count
|
|
24
|
+
bx.assessFit(res) # 2×2 diagnostic panel
|
|
25
|
+
|
|
26
|
+
adjM = bx.getAdjMat(res) # P×P adjacency matrix
|
|
27
|
+
clust = bx.graphComponents(adjM, minCtr=2) # disjoint clusters
|
|
28
|
+
bx.plotBitmapCC(adjM, clust) # bitmap of adjacency
|
|
29
|
+
bx.plotCluster(adjM, 1, clust, labels=True) # network plot of cluster 1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Input convention
|
|
33
|
+
|
|
34
|
+
`betaMix()` expects **M as N×P** — N samples in rows, P variables in columns — matching numpy's `corrcoef(M, rowvar=False)` and the R `betaMix` package.
|
|
35
|
+
|
|
36
|
+
> **Upgrading from ≤ 0.1.4?** Remove any `.T` transpose and update code that unpacked the previous tuple return value. See [NEWS.md](NEWS.md) for the full list of breaking changes.
|
|
37
|
+
|
|
38
|
+
## Key functions
|
|
39
|
+
|
|
40
|
+
### Fitting and diagnostics
|
|
41
|
+
|
|
42
|
+
| Function | Description |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `betaMix(M, ...)` | Fit the two-component Beta mixture; returns a `dict` |
|
|
45
|
+
| `shortSummary(res)` | Print parameter estimates and edge count |
|
|
46
|
+
| `assessFit(res)` | 2×2 panel: mixture histogram, null Q-Q, non-null Q-Q, ROC |
|
|
47
|
+
| `plotFittedBetaMix(res)` | Fitted mixture density on log scale |
|
|
48
|
+
| `plotROC(res)` | Model-based ROC; returns AUC and Youden-index threshold |
|
|
49
|
+
| `plotNonNullDensity(res)` | Kernel density of non-null z_j values |
|
|
50
|
+
|
|
51
|
+
### Network analysis
|
|
52
|
+
|
|
53
|
+
| Function | Description |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `getAdjMat(res, ...)` | Build P×P adjacency matrix; `signed=True` for −1/0/1 |
|
|
56
|
+
| `graphComponents(A, ...)` | Disjoint clusters via centrality-based assignment |
|
|
57
|
+
| `sphericalCaps(A, ...)` | Hub-and-spoke clustering (greedy, degree-ordered) |
|
|
58
|
+
| `greedyBasis(A, strategy, ...)` | **Overlapping communities** via maximal independent set |
|
|
59
|
+
| `summarizeClusters(ci)` | Five-number summary per cluster |
|
|
60
|
+
| `summarizeBasis(bi)` | Summary for a `greedyBasis()` result |
|
|
61
|
+
| `collapsedGraph(res, ci)` | Adjacency matrix reduced to cluster centres |
|
|
62
|
+
| `shortestPathDistance(A, numSteps)` | Multi-hop distances in the network |
|
|
63
|
+
| `clusteringCoef(A)` | Vectorised clustering coefficients |
|
|
64
|
+
|
|
65
|
+
### Visualisation
|
|
66
|
+
|
|
67
|
+
| Function | Description |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `plotBitmapCC(A, ...)` | Bitmap heatmap of adjacency, coloured by cluster |
|
|
70
|
+
| `plotCluster(A, n, ci, ...)` | Force-directed network plot of cluster `n` |
|
|
71
|
+
| `plotDegCC(res, ci)` | Degree vs clustering coefficient scatter |
|
|
72
|
+
|
|
73
|
+
## `betaMix()` parameters
|
|
74
|
+
|
|
75
|
+
| Parameter | Default | Meaning |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `M` | required | N×P DataFrame or array |
|
|
78
|
+
| `ind` | `True` | Independent samples? `False` estimates an effective sample size ν |
|
|
79
|
+
| `maxalpha` | `1e-4` | Per-pair frequentist Type I error bound (use `1e-6` for P > 1000) |
|
|
80
|
+
| `ppr` | `0.05` | Posterior null probability threshold for calling an edge |
|
|
81
|
+
| `method` | `"pearson"` | `"pearson"` or `"spearman"` |
|
|
82
|
+
| `subsamplesize` | `50000` | Pairs subsampled for EM; ≥ 20 000 required (ignored if smaller) |
|
|
83
|
+
| `bmax` | `0.999` | Upper bound of non-null support |
|
|
84
|
+
| `seed` | `912469` | Random seed for subsampling reproducibility |
|
|
85
|
+
| `msg` | `False` | Print EM iteration progress |
|
|
86
|
+
|
|
87
|
+
**Returns** a dict with: `angleMat`, `z_j`, `m0`, `p0`, `ahat`, `bhat`, `etahat`, `ppthr`, `nodes`, `edges`, `bmax`, `N`, `cnt`, `method`.
|
|
88
|
+
|
|
89
|
+
## Overlapping communities with `greedyBasis()`
|
|
90
|
+
|
|
91
|
+
Unlike `graphComponents` (disjoint) and `sphericalCaps` (hub-centric), `greedyBasis` finds a **maximal independent set (MIS)**: a set of mutually non-adjacent representative nodes. Each remaining node is then assigned to every community whose centre it is adjacent to, giving overlapping membership.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
adjM = bx.getAdjMat(res)
|
|
95
|
+
basis = bx.greedyBasis(adjM, strategy="min_degree", labels=M.columns)
|
|
96
|
+
# columns: node, isBasis, basisOrder, degree, cc, nCovered, nCommunities, communities
|
|
97
|
+
|
|
98
|
+
bx.summarizeBasis(basis)
|
|
99
|
+
|
|
100
|
+
# Nodes in multiple communities simultaneously:
|
|
101
|
+
bridges = basis[basis["nCommunities"] > 1]
|
|
102
|
+
|
|
103
|
+
# Members of the community centred on node 5:
|
|
104
|
+
community5 = basis[basis["communities"].apply(lambda c: 5 in c)]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Two strategies:
|
|
108
|
+
|
|
109
|
+
| Strategy | Selects first | Basis size | Community size | Overlap |
|
|
110
|
+
|---|---|---|---|---|
|
|
111
|
+
| `"min_degree"` (default) | Least-connected node | Larger | Smaller | Higher |
|
|
112
|
+
| `"max_degree"` | Most-connected hub | Smaller | Larger | Lower |
|
|
113
|
+
|
|
114
|
+
**Guaranteed properties**: no two basis nodes share an edge (independence); every non-basis node has at least one basis neighbour (maximality).
|
|
115
|
+
|
|
116
|
+
## Choosing the right clustering function
|
|
117
|
+
|
|
118
|
+
| | `graphComponents` | `sphericalCaps` | `greedyBasis` |
|
|
119
|
+
|---|---|---|---|
|
|
120
|
+
| Membership | Disjoint | Overlapping | Overlapping |
|
|
121
|
+
| Basis nodes adjacent? | Yes | Yes | **No** (independent set) |
|
|
122
|
+
| Selection criterion | Max degree × cc | Max degree | Min or max degree |
|
|
123
|
+
| Best for | General clusters | Hub-spoke networks | Non-redundant representatives |
|
|
124
|
+
|
|
125
|
+
## What's new in 0.2.x
|
|
126
|
+
|
|
127
|
+
See [NEWS.md](NEWS.md) for the full changelog. Highlights:
|
|
128
|
+
|
|
129
|
+
- **0.2.1**: `getAdjMat` edge count now matches `betaMix()`; fixed a
|
|
130
|
+
`plotFittedBetaMix` crash; unused dependencies removed; full test suite
|
|
131
|
+
|
|
132
|
+
- **`greedyBasis()`** — overlapping community detection via MIS
|
|
133
|
+
- **Input convention**: M is now N×P (remove any `.T` in existing code)
|
|
134
|
+
- **`betaMix()` returns a `dict`** instead of a tuple
|
|
135
|
+
- **`method="spearman"`** for rank-based correlation
|
|
136
|
+
- **`assessFit()`**, **`plotROC()`**, **`plotNonNullDensity()`** — new diagnostics
|
|
137
|
+
- **Vectorised `clusteringCoef()`** — approximately 10–80× faster
|
|
138
|
+
- Analytic Jacobian for MLE; `brentq` for eta estimation — matching R's solvers
|
|
139
|
+
- Python is approximately 3× faster than R on large benchmark datasets
|
|
140
|
+
|
|
141
|
+
## See also
|
|
142
|
+
|
|
143
|
+
- R package: [github.com/haimbar/betaMix](https://github.com/haimbar/betaMix)
|
|
144
|
+
- LLM-friendly function reference: [llms.txt](llms.txt)
|
|
145
|
+
- Version history: [NEWS.md](NEWS.md)
|
|
146
|
+
- Additional examples and data: [code/](code/), [data/](data/), [doc/](doc/)
|
|
147
|
+
|
|
148
|
+
## References
|
|
149
|
+
|
|
150
|
+
Bar, H. & Wells, M. T. (2023). On graphical models and convex geometry. *Computational Statistics & Data Analysis*, 187, 107800. https://doi.org/10.1016/j.csda.2023.107800
|
|
151
|
+
|
|
152
|
+
Frankl, P. & Maehara, H. (1990). Some geometric applications of the beta distribution. *Annals of the Institute of Statistical Mathematics*, 42(3), 463–474.
|