critical-es-value 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,32 @@
1
+ name: Upload Python Package to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [created]
6
+
7
+ jobs:
8
+ pypi-publish:
9
+ name: Publish release to PyPI
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v4
19
+
20
+ - name: "Set up Python"
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version-file: ".python-version"
24
+
25
+ - name: Install the project
26
+ run: uv sync --all-extras --dev
27
+
28
+ - name: Build
29
+ run: uv build
30
+
31
+ - name: Publish to PyPI
32
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,16 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Jupyter
13
+ .ipynb_checkpoints
14
+
15
+ *.ipynb
16
+ data*.csv
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Florian Rohrer
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,112 @@
1
+ Metadata-Version: 2.4
2
+ Name: critical-es-value
3
+ Version: 0.1.0
4
+ Summary: Calculate critical effect size values.
5
+ Author-email: Florian Rohrer <semicolonator@gmail.com>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.13
8
+ Requires-Dist: mpmath>=1.3.0
9
+ Requires-Dist: pandas>=2.3.3
10
+ Requires-Dist: pingouin>=0.5.5
11
+ Description-Content-Type: text/markdown
12
+
13
+ # critical_es_value
14
+
15
+ Calculate critical effect size values for t-Tests, correlation tests and linear regression coefficients.
16
+
17
+ ## Usage
18
+
19
+ ```python
20
+ import numpy as np
21
+ import pingouin as pg
22
+
23
+ from critical_es_value import (
24
+ critical_for_one_sample_ttest,
25
+ critical_for_two_sample_ttest,
26
+ critical_for_correlation_test,
27
+ critical_for_linear_regression,
28
+ )
29
+
30
+ np.random.seed(123)
31
+ mean, cov, n = [4, 5], [(1, .6), (.6, 1)], 30
32
+ x, y = np.random.multivariate_normal(mean, cov, n).T
33
+ ```
34
+
35
+ ### t-Test
36
+
37
+
38
+ ```python
39
+ pg.ttest(x, 0)
40
+ critical_for_one_sample_ttest(x)
41
+ ```
42
+
43
+ | | T | dof | alternative | p-val | CI95% | cohen-d | BF10 | power |
44
+ |:-------|--------:|------:|:--------------|------------:|:------------|----------:|----------:|--------:|
45
+ | T-test | 16.0765 | 29 | two-sided | 5.54732e-16 | [3.37 4.35] | 2.93515 | 1.031e+13 | nan |
46
+
47
+ | | T | dof | T_critical | d | d_critical | b_critical | g | g_critical |
48
+ |:---------|--------:|------:|-------------:|--------:|-------------:|-------------:|--------:|-------------:|
49
+ | critical | 16.0765 | 29 | 2.04523 | 2.93515 | 0.373406 | 0.491162 | 2.85847 | 0.363651 |
50
+
51
+ ```python
52
+ pg.ttest(x, y)
53
+ critical_for_two_sample_ttest(x, y)
54
+ ```
55
+
56
+ | | T | dof | alternative | p-val | CI95% | cohen-d | BF10 | power |
57
+ |:-------|---------:|------:|:--------------|----------:|:--------------|----------:|-------:|---------:|
58
+ | T-test | -3.40071 | 58 | two-sided | 0.0012224 | [-1.68 -0.43] | 0.878059 | 26.155 | 0.916807 |
59
+
60
+
61
+ | | T | dof | T_critical | d | d_critical | b_critical | g | g_critical |
62
+ |:---------|---------:|------:|-------------:|----------:|-------------:|-------------:|----------:|-------------:|
63
+ | critical | -3.40071 | 58 | 2.00172 | -0.878059 | 0.516841 | 0.62077 | -0.866647 | 0.510124 |
64
+
65
+
66
+ ### Correlation Test
67
+
68
+ ```python
69
+ pg.corr(x, y)
70
+ critical_for_correlation_test(x, y)
71
+ ```
72
+
73
+ | | n | r | CI95% | p-val | BF10 | power |
74
+ |:--------|----:|---------:|:------------|-----------:|-------:|---------:|
75
+ | pearson | 30 | 0.594785 | [0.3 0.79] | 0.00052736 | 69.723 | 0.950373 |
76
+
77
+ | | n | r | dof | r_critical | se_r | se_r_critical |
78
+ |:---------|----:|---------:|------:|-------------:|--------:|----------------:|
79
+ | critical | 30 | 0.594785 | 28 | 0.361007 | 0.15192 | 0.176238 |
80
+
81
+
82
+ ### Linear Regression
83
+
84
+ ```python
85
+ import pandas as pd
86
+
87
+ np.random.seed(123)
88
+ data = pd.DataFrame({"X": x, "Y": y, "Z": np.random.normal(5, 1, 30)})
89
+
90
+ pg.linear_regression(data[["X", "Z"]], data["Y"])
91
+ critical_for_linear_regression(data[["X", "Z"]], data["Y"])
92
+ ```
93
+
94
+ | | names | coef | se | T | pval | r2 | adj_r2 | CI[2.5%] | CI[97.5%] |
95
+ |---:|:----------|-----------:|---------:|----------:|------------:|---------:|---------:|-----------:|------------:|
96
+ | 0 | Intercept | 3.15799 | 0.844129 | 3.74112 | 0.000874245 | 0.354522 | 0.306709 | 1.42598 | 4.88999 |
97
+ | 1 | X | 0.487772 | 0.126736 | 3.84871 | 0.000659501 | 0.354522 | 0.306709 | 0.22773 | 0.747814 |
98
+ | 2 | Z | -0.0249309 | 0.140417 | -0.177548 | 0.860403 | 0.354522 | 0.306709 | -0.313044 | 0.263182 |
99
+
100
+ | | names | coef | coef_critical |
101
+ |---:|:----------|-----------:|----------------:|
102
+ | 0 | Intercept | 3.15799 | 1.73201 |
103
+ | 1 | X | 0.487772 | 0.260042 |
104
+ | 2 | Z | -0.0249309 | 0.288113 |
105
+
106
+
107
+ ## Resources
108
+
109
+ * [R package](https://psicostat.github.io/criticalESvalue/index.html)
110
+ * [Original paper](https://journals.sagepub.com/doi/10.1177/25152459251335298?icid=int.sj-full-text.similar-articles.5)
111
+ > Perugini, A., Gambarota, F., Toffalini, E., Lakens, D., Pastore, M., Finos, L., ... & Altoè, G. (2025). The Benefits of Reporting Critical-Effect-Size Values. Advances in Methods and Practices in Psychological Science, 8(2), 25152459251335298.
112
+
@@ -0,0 +1,100 @@
1
+ # critical_es_value
2
+
3
+ Calculate critical effect size values for t-Tests, correlation tests and linear regression coefficients.
4
+
5
+ ## Usage
6
+
7
+ ```python
8
+ import numpy as np
9
+ import pingouin as pg
10
+
11
+ from critical_es_value import (
12
+ critical_for_one_sample_ttest,
13
+ critical_for_two_sample_ttest,
14
+ critical_for_correlation_test,
15
+ critical_for_linear_regression,
16
+ )
17
+
18
+ np.random.seed(123)
19
+ mean, cov, n = [4, 5], [(1, .6), (.6, 1)], 30
20
+ x, y = np.random.multivariate_normal(mean, cov, n).T
21
+ ```
22
+
23
+ ### t-Test
24
+
25
+
26
+ ```python
27
+ pg.ttest(x, 0)
28
+ critical_for_one_sample_ttest(x)
29
+ ```
30
+
31
+ | | T | dof | alternative | p-val | CI95% | cohen-d | BF10 | power |
32
+ |:-------|--------:|------:|:--------------|------------:|:------------|----------:|----------:|--------:|
33
+ | T-test | 16.0765 | 29 | two-sided | 5.54732e-16 | [3.37 4.35] | 2.93515 | 1.031e+13 | nan |
34
+
35
+ | | T | dof | T_critical | d | d_critical | b_critical | g | g_critical |
36
+ |:---------|--------:|------:|-------------:|--------:|-------------:|-------------:|--------:|-------------:|
37
+ | critical | 16.0765 | 29 | 2.04523 | 2.93515 | 0.373406 | 0.491162 | 2.85847 | 0.363651 |
38
+
39
+ ```python
40
+ pg.ttest(x, y)
41
+ critical_for_two_sample_ttest(x, y)
42
+ ```
43
+
44
+ | | T | dof | alternative | p-val | CI95% | cohen-d | BF10 | power |
45
+ |:-------|---------:|------:|:--------------|----------:|:--------------|----------:|-------:|---------:|
46
+ | T-test | -3.40071 | 58 | two-sided | 0.0012224 | [-1.68 -0.43] | 0.878059 | 26.155 | 0.916807 |
47
+
48
+
49
+ | | T | dof | T_critical | d | d_critical | b_critical | g | g_critical |
50
+ |:---------|---------:|------:|-------------:|----------:|-------------:|-------------:|----------:|-------------:|
51
+ | critical | -3.40071 | 58 | 2.00172 | -0.878059 | 0.516841 | 0.62077 | -0.866647 | 0.510124 |
52
+
53
+
54
+ ### Correlation Test
55
+
56
+ ```python
57
+ pg.corr(x, y)
58
+ critical_for_correlation_test(x, y)
59
+ ```
60
+
61
+ | | n | r | CI95% | p-val | BF10 | power |
62
+ |:--------|----:|---------:|:------------|-----------:|-------:|---------:|
63
+ | pearson | 30 | 0.594785 | [0.3 0.79] | 0.00052736 | 69.723 | 0.950373 |
64
+
65
+ | | n | r | dof | r_critical | se_r | se_r_critical |
66
+ |:---------|----:|---------:|------:|-------------:|--------:|----------------:|
67
+ | critical | 30 | 0.594785 | 28 | 0.361007 | 0.15192 | 0.176238 |
68
+
69
+
70
+ ### Linear Regression
71
+
72
+ ```python
73
+ import pandas as pd
74
+
75
+ np.random.seed(123)
76
+ data = pd.DataFrame({"X": x, "Y": y, "Z": np.random.normal(5, 1, 30)})
77
+
78
+ pg.linear_regression(data[["X", "Z"]], data["Y"])
79
+ critical_for_linear_regression(data[["X", "Z"]], data["Y"])
80
+ ```
81
+
82
+ | | names | coef | se | T | pval | r2 | adj_r2 | CI[2.5%] | CI[97.5%] |
83
+ |---:|:----------|-----------:|---------:|----------:|------------:|---------:|---------:|-----------:|------------:|
84
+ | 0 | Intercept | 3.15799 | 0.844129 | 3.74112 | 0.000874245 | 0.354522 | 0.306709 | 1.42598 | 4.88999 |
85
+ | 1 | X | 0.487772 | 0.126736 | 3.84871 | 0.000659501 | 0.354522 | 0.306709 | 0.22773 | 0.747814 |
86
+ | 2 | Z | -0.0249309 | 0.140417 | -0.177548 | 0.860403 | 0.354522 | 0.306709 | -0.313044 | 0.263182 |
87
+
88
+ | | names | coef | coef_critical |
89
+ |---:|:----------|-----------:|----------------:|
90
+ | 0 | Intercept | 3.15799 | 1.73201 |
91
+ | 1 | X | 0.487772 | 0.260042 |
92
+ | 2 | Z | -0.0249309 | 0.288113 |
93
+
94
+
95
+ ## Resources
96
+
97
+ * [R package](https://psicostat.github.io/criticalESvalue/index.html)
98
+ * [Original paper](https://journals.sagepub.com/doi/10.1177/25152459251335298?icid=int.sj-full-text.similar-articles.5)
99
+ > Perugini, A., Gambarota, F., Toffalini, E., Lakens, D., Pastore, M., Finos, L., ... & Altoè, G. (2025). The Benefits of Reporting Critical-Effect-Size Values. Advances in Methods and Practices in Psychological Science, 8(2), 25152459251335298.
100
+
@@ -0,0 +1,30 @@
1
+ [project]
2
+ name = "critical-es-value"
3
+ version = "0.1.0"
4
+ description = "Calculate critical effect size values."
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "mpmath>=1.3.0",
9
+ "pandas>=2.3.3",
10
+ "pingouin>=0.5.5",
11
+ ]
12
+ authors = [
13
+ {name = "Florian Rohrer", email = "semicolonator@gmail.com"},
14
+ ]
15
+
16
+ [build-system]
17
+ requires = ["hatchling"]
18
+ build-backend = "hatchling.build"
19
+
20
+ [tool.uv]
21
+ dev-dependencies = [
22
+ "jupyter>=1.1.1",
23
+ "pytest>=8.4.2",
24
+ ]
25
+
26
+ [tool.pytest.ini_options]
27
+ pythonpath = ["src"]
28
+
29
+ [tool.hatch.build.targets.wheel]
30
+ packages = ["src/critical_es_value"]
@@ -0,0 +1,13 @@
1
+ from .corrtest import critical_for_correlation_test
2
+ from .linreg import (
3
+ critical_for_linear_regression,
4
+ critical_for_linear_regression_se_coefficients,
5
+ )
6
+ from .ttest import (
7
+ critical_for_one_sample_ttest,
8
+ critical_for_two_sample_ttest,
9
+ )
10
+ from .utils import (
11
+ get_alpha,
12
+ get_bias_correction_factor_J,
13
+ )
@@ -0,0 +1,72 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import pingouin
4
+ from numpy.typing import ArrayLike
5
+ from scipy import stats
6
+
7
+ from critical_es_value import utils
8
+
9
+
10
+ def critical_for_correlation_test(
11
+ x: ArrayLike,
12
+ y: ArrayLike,
13
+ confidence: float = 0.95,
14
+ alternative: str = "two-sided",
15
+ variant: str = "ttest",
16
+ ) -> pd.DataFrame:
17
+ """Calculate critical effect size values for a pearson correlation test.
18
+
19
+ Returns a DataFrame with the following columns:
20
+ - r: Pearson correlation coefficient
21
+ - n: Sample size
22
+ - dof: Degrees of freedom
23
+ - r_critical: Critical value for the correlation coefficient
24
+ - rz_critical: Critical value for Fisher's z-transformed correlation coefficient (only for "ztest" variant)
25
+ - se_r: Standard error of the correlation coefficient
26
+ - se_r_critical: Standard error of the critical correlation coefficient
27
+ - se_rz_critical: Standard error of the critical Fisher's z-transformed correlation coefficient (only for "ztest" variant)
28
+
29
+ Args:
30
+ x (ArrayLike): Sample data for group 1.
31
+ y (ArrayLike): Sample data for group 2.
32
+ confidence (float): Confidence level between 0 and 1 (exclusive). Default is 0.95.
33
+ alternative (str): The alternative hypothesis. Either "two-sided", "greater", or "less". Default is "two-sided".
34
+ variant (str): The statistical test variant. Either "ttest" or "ztest". Default is "ttest".
35
+
36
+ Returns:
37
+ pd.DataFrame: A DataFrame containing critical effect size values.
38
+ """
39
+
40
+ if variant not in ["ttest", "ztest"]:
41
+ raise ValueError("variant must be one of 'ttest' or 'ztest'")
42
+
43
+ corr_test_result = pingouin.corr(
44
+ x, y, alternative=alternative, method="pearson"
45
+ ).iloc[0]
46
+
47
+ r = corr_test_result["r"]
48
+ n = corr_test_result["n"]
49
+
50
+ alpha = utils.get_alpha(confidence, alternative)
51
+ dof = n - 2
52
+
53
+ if variant == "ttest":
54
+ tc = np.abs(stats.t.ppf(alpha, dof))
55
+ rc = np.sqrt(tc**2 / (tc**2 + dof))
56
+ else:
57
+ zc = np.abs(stats.norm.ppf(alpha))
58
+ rc = np.tanh(zc / np.sqrt(n - 3))
59
+
60
+ result = {
61
+ "n": n,
62
+ "r": r,
63
+ "dof": dof,
64
+ "r_critical": rc,
65
+ "se_r": np.sqrt((1 - r**2) / dof),
66
+ "se_r_critical": np.sqrt((1 - rc**2) / dof),
67
+ }
68
+ if variant == "ztest":
69
+ result["rz_critical"] = np.atanh(rc)
70
+ result["se_rz_critical"] = 1 / np.sqrt(n - 3)
71
+
72
+ return pd.DataFrame([result], index=["critical"])
@@ -0,0 +1,97 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import pingouin
4
+ from numpy.typing import ArrayLike
5
+ from scipy import stats
6
+
7
+ from critical_es_value import utils
8
+
9
+
10
+ def critical_for_linear_regression_se_coefficients(
11
+ se_coefficients: ArrayLike,
12
+ dof: int,
13
+ confidence: float,
14
+ alternative: str,
15
+ variant: str = "ttest",
16
+ ) -> list[float]:
17
+ """Calculate critical effect size values for linear regression coefficients.
18
+
19
+ Args:
20
+ se_coefficients (ArrayLike): Standard errors of the regression coefficients.
21
+ dof (int): Degrees of freedom of the model residuals.
22
+ confidence (float): Confidence level between 0 and 1 (exclusive).
23
+ alternative (str): The alternative hypothesis. Either "two-sided", "greater", or "less".
24
+ variant (str): The statistical test variant. Either "ttest" or "ztest". Default is "ttest".
25
+
26
+ Returns:
27
+ np.ndarray: An array containing critical effect size values for each coefficient.
28
+
29
+ Raises:
30
+ ValueError: If variant is not one of "ttest" or "ztest".
31
+ """
32
+ if variant not in ["ttest", "ztest"]:
33
+ raise ValueError("variant must be one of 'ttest' or 'ztest'")
34
+
35
+ alpha = utils.get_alpha(confidence, alternative)
36
+
37
+ if variant == "ttest":
38
+ qc = np.abs(stats.t.ppf(alpha, dof))
39
+ else:
40
+ qc = np.abs(stats.norm.ppf(alpha))
41
+
42
+ return qc * np.array(se_coefficients)
43
+
44
+
45
+ def critical_for_linear_regression(
46
+ X: pd.DataFrame,
47
+ y: pd.Series,
48
+ alternative: str = "two-sided",
49
+ confidence: float = 0.95,
50
+ variant: str = "ttest",
51
+ **kwargs,
52
+ ):
53
+ """Calculate critical effect size values for linear regression coefficients.
54
+
55
+ Returns a DataFrame with the following columns:
56
+ - names: Names of the regression coefficients
57
+ - coef: Estimated regression coefficients
58
+ - coef_critical: Critical value for the regression coefficients
59
+
60
+ Args:
61
+ X (pd.DataFrame): DataFrame containing the independent variables.
62
+ y (pd.Series): Series containing the dependent variable.
63
+ alternative (str): The alternative hypothesis. Either "two-sided", "greater", or "less". Default is "two-sided".
64
+ confidence (float): Confidence level between 0 and 1 (exclusive). Default is 0.95.
65
+ variant (str): The statistical test variant. Either "ttest" or "ztest". Default is "ttest".
66
+ **kwargs: Additional keyword arguments to pass to pingouin.linear_regression.
67
+
68
+ Returns:
69
+ pd.DataFrame: A DataFrame containing critical effect size values.
70
+
71
+ Raises:
72
+ ValueError: If variant is not one of "ttest" or "ztest".
73
+ """
74
+ if variant not in ["ttest", "ztest"]:
75
+ raise ValueError("variant must be one of 'ttest' or 'ztest'")
76
+
77
+ alpha = utils.get_alpha(confidence, alternative)
78
+
79
+ model = pingouin.linear_regression(X=X, y=y, alpha=alpha, **kwargs)
80
+ coef = model["coef"].values
81
+
82
+ coef_critical = critical_for_linear_regression_se_coefficients(
83
+ se_coefficients=model["se"].values,
84
+ dof=model.df_resid_,
85
+ confidence=confidence,
86
+ alternative=alternative,
87
+ variant=variant,
88
+ )
89
+
90
+ return pd.DataFrame(
91
+ {
92
+ "names": model["names"].values,
93
+ "coef": coef,
94
+ "coef_critical": coef_critical,
95
+ },
96
+ index=list(range(len(coef))),
97
+ )