py2ls 0.1.9.3__py3-none-any.whl → 0.1.9.5__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.
- py2ls/.DS_Store +0 -0
- py2ls/.git/COMMIT_EDITMSG +1 -1
- py2ls/.git/FETCH_HEAD +1 -1
- py2ls/.git/index +0 -0
- py2ls/.git/logs/HEAD +1 -0
- py2ls/.git/logs/refs/heads/main +1 -0
- py2ls/.git/logs/refs/remotes/origin/HEAD +2 -0
- py2ls/.git/logs/refs/remotes/origin/main +1 -0
- py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
- py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
- py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
- py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
- py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
- py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
- py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
- py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
- py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
- py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +2 -0
- py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
- py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
- py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
- py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
- py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +5 -0
- py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
- py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +3 -0
- py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
- py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
- py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
- py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
- py2ls/.git/refs/heads/main +1 -1
- py2ls/.git/refs/remotes/origin/main +1 -1
- py2ls/data/styles/example/style1.pdf +0 -0
- py2ls/data/styles/example/style2.pdf +0 -0
- py2ls/data/styles/example/style3.pdf +0 -0
- py2ls/data/styles/example/style4.pdf +0 -0
- py2ls/data/styles/example/style5.pdf +0 -0
- py2ls/data/styles/example/style6.pdf +0 -0
- py2ls/data/styles/example/style7.pdf +0 -0
- py2ls/data/styles/example/style8.pdf +0 -0
- py2ls/data/styles/example/style9.pdf +0 -0
- py2ls/data/styles/style6.json +31 -20
- py2ls/data/styles/style7.json +201 -0
- py2ls/data/styles/style8.json +199 -0
- py2ls/data/styles/style9.json +215 -0
- py2ls/netfinder.py +0 -8
- py2ls/plot.py +561 -126
- py2ls/stats.py +182 -372
- {py2ls-0.1.9.3.dist-info → py2ls-0.1.9.5.dist-info}/METADATA +1 -1
- {py2ls-0.1.9.3.dist-info → py2ls-0.1.9.5.dist-info}/RECORD +50 -17
- {py2ls-0.1.9.3.dist-info → py2ls-0.1.9.5.dist-info}/WHEEL +0 -0
py2ls/stats.py
CHANGED
@@ -12,7 +12,7 @@ warnings.filterwarnings("ignore", category=RuntimeWarning)
|
|
12
12
|
|
13
13
|
# FuncStars --v 0.1.1
|
14
14
|
def FuncStars(
|
15
|
-
ax,
|
15
|
+
ax=None,
|
16
16
|
pval=None,
|
17
17
|
ylim=None,
|
18
18
|
xlim=None,
|
@@ -33,10 +33,11 @@ def FuncStars(
|
|
33
33
|
linewidth=0.8,
|
34
34
|
nsshow="off",
|
35
35
|
symbolcolor="k",
|
36
|
-
tailindicator=[0.
|
36
|
+
tailindicator=[0.05, 0.05],
|
37
37
|
report=None,
|
38
38
|
report_scale=-0.1,
|
39
39
|
report_loc=None,
|
40
|
+
**kwargs
|
40
41
|
):
|
41
42
|
if ax is None:
|
42
43
|
ax = plt.gca()
|
@@ -51,138 +52,141 @@ def FuncStars(
|
|
51
52
|
yscale = np.float64(yscale)
|
52
53
|
if y_loc is None:
|
53
54
|
y_loc = np.min(ylim) + yscale * (np.max(ylim) - np.min(ylim))
|
55
|
+
else:
|
56
|
+
y_loc=y_loc+(1-yscale) * np.abs(np.diff(ylim))+0.1 *y_loc
|
54
57
|
xcenter = np.mean([x1, x2])
|
55
|
-
|
56
|
-
|
57
|
-
if
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
if pval is not None:
|
59
|
+
# ns / *
|
60
|
+
if alpha < pval:
|
61
|
+
if nsshow == "on":
|
62
|
+
ns_str = f"p={round(pval, 3)}" if pval < 0.9 else "ns"
|
63
|
+
color = "m" if pval < 0.1 else "k"
|
64
|
+
ax.text(
|
65
|
+
xcenter,
|
66
|
+
y_loc,
|
67
|
+
ns_str,
|
68
|
+
ha="center",
|
69
|
+
va="bottom", # 'center_baseline',
|
70
|
+
fontsize=fontsize - 6 if fontsize > 6 else fontsize,
|
71
|
+
fontname=fontname,
|
72
|
+
color=color,
|
73
|
+
rotation=rotation,
|
74
|
+
# bbox=dict(facecolor=None, edgecolor=None, color=None, linewidth=None)
|
75
|
+
)
|
76
|
+
elif 0.01 < pval <= alpha:
|
77
|
+
ax.text(
|
61
78
|
xcenter,
|
62
79
|
y_loc,
|
63
|
-
|
80
|
+
symbol,
|
64
81
|
ha="center",
|
65
|
-
va="
|
66
|
-
fontsize=fontsize
|
82
|
+
va="top",#"center_baseline",
|
83
|
+
fontsize=fontsize,
|
67
84
|
fontname=fontname,
|
68
|
-
color=
|
69
|
-
rotation=rotation,
|
70
|
-
# bbox=dict(facecolor=None, edgecolor=None, color=None, linewidth=None)
|
85
|
+
color=symbolcolor,
|
71
86
|
)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
)
|
83
|
-
elif 0.001 < pval <= 0.01:
|
84
|
-
plt.text(
|
85
|
-
xcenter,
|
86
|
-
y_loc,
|
87
|
-
symbol * 2,
|
88
|
-
ha="center",
|
89
|
-
va="center_baseline",
|
90
|
-
fontsize=fontsize,
|
91
|
-
fontname=fontname,
|
92
|
-
color=symbolcolor,
|
93
|
-
)
|
94
|
-
elif 0 < pval <= 0.001:
|
95
|
-
plt.text(
|
96
|
-
xcenter,
|
97
|
-
y_loc,
|
98
|
-
symbol * 3,
|
99
|
-
ha="center",
|
100
|
-
va="center_baseline",
|
101
|
-
fontsize=fontsize,
|
102
|
-
fontname=fontname,
|
103
|
-
color=symbolcolor,
|
104
|
-
)
|
105
|
-
# lines indicators
|
106
|
-
if linego and 0 < pval <= 0.05:
|
107
|
-
# horizontal line
|
108
|
-
if yscale <= 0.99:
|
109
|
-
plt.plot(
|
110
|
-
[x1 + np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
111
|
-
[
|
112
|
-
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
113
|
-
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
114
|
-
],
|
115
|
-
linestyle=linestyle,
|
116
|
-
color=linecolor,
|
117
|
-
linewidth=linewidth,
|
118
|
-
)
|
119
|
-
# vertical line
|
120
|
-
plt.plot(
|
121
|
-
[x1 + np.abs(np.diff(xlim)) * 0.01, x1 + np.abs(np.diff(xlim)) * 0.01],
|
122
|
-
[
|
123
|
-
y_loc - np.abs(np.diff(ylim)) * tailindicator[0],
|
124
|
-
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
125
|
-
],
|
126
|
-
linestyle=linestyle,
|
127
|
-
color=linecolor,
|
128
|
-
linewidth=linewidth,
|
129
|
-
)
|
130
|
-
plt.plot(
|
131
|
-
[x2 - np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
132
|
-
[
|
133
|
-
y_loc - np.abs(np.diff(ylim)) * tailindicator[1],
|
134
|
-
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
135
|
-
],
|
136
|
-
linestyle=linestyle,
|
137
|
-
color=linecolor,
|
138
|
-
linewidth=linewidth,
|
139
|
-
)
|
140
|
-
else:
|
141
|
-
plt.plot(
|
142
|
-
[x1 + np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
143
|
-
[
|
144
|
-
np.min(ylim)
|
145
|
-
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
146
|
-
- np.abs(np.diff(ylim)) * 0.002,
|
147
|
-
np.min(ylim)
|
148
|
-
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
149
|
-
- np.abs(np.diff(ylim)) * 0.002,
|
150
|
-
],
|
151
|
-
linestyle=linestyle,
|
152
|
-
color=linecolor,
|
153
|
-
linewidth=linewidth,
|
154
|
-
)
|
155
|
-
# vertical line
|
156
|
-
plt.plot(
|
157
|
-
[x1 + np.abs(np.diff(xlim)) * 0.01, x1 + np.abs(np.diff(xlim)) * 0.01],
|
158
|
-
[
|
159
|
-
np.min(ylim)
|
160
|
-
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
161
|
-
- np.abs(np.diff(ylim)) * tailindicator[0],
|
162
|
-
np.min(ylim)
|
163
|
-
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
164
|
-
- np.abs(np.diff(ylim)) * 0.002,
|
165
|
-
],
|
166
|
-
linestyle=linestyle,
|
167
|
-
color=linecolor,
|
168
|
-
linewidth=linewidth,
|
87
|
+
elif 0.001 < pval <= 0.01:
|
88
|
+
ax.text(
|
89
|
+
xcenter,
|
90
|
+
y_loc,
|
91
|
+
symbol * 2,
|
92
|
+
ha="center",
|
93
|
+
va="top",#"center_baseline",
|
94
|
+
fontsize=fontsize,
|
95
|
+
fontname=fontname,
|
96
|
+
color=symbolcolor,
|
169
97
|
)
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
linestyle=linestyle,
|
181
|
-
color=linecolor,
|
182
|
-
linewidth=linewidth,
|
98
|
+
elif 0 < pval <= 0.001:
|
99
|
+
ax.text(
|
100
|
+
xcenter,
|
101
|
+
y_loc,
|
102
|
+
symbol * 3,
|
103
|
+
ha="center",
|
104
|
+
va="top",#"center_baseline",
|
105
|
+
fontsize=fontsize,
|
106
|
+
fontname=fontname,
|
107
|
+
color=symbolcolor,
|
183
108
|
)
|
109
|
+
# lines indicators
|
110
|
+
if linego and 0 < pval <= 0.05:
|
111
|
+
# horizontal line
|
112
|
+
if yscale <= 0.99:
|
113
|
+
ax.plot(
|
114
|
+
[x1 + np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
115
|
+
[
|
116
|
+
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
117
|
+
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
118
|
+
],
|
119
|
+
linestyle=linestyle,
|
120
|
+
color=linecolor,
|
121
|
+
linewidth=linewidth,
|
122
|
+
)
|
123
|
+
# vertical line
|
124
|
+
ax.plot(
|
125
|
+
[x1 + np.abs(np.diff(xlim)) * 0.01, x1 + np.abs(np.diff(xlim)) * 0.01],
|
126
|
+
[
|
127
|
+
y_loc - np.abs(np.diff(ylim)) * tailindicator[0],
|
128
|
+
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
129
|
+
],
|
130
|
+
linestyle=linestyle,
|
131
|
+
color=linecolor,
|
132
|
+
linewidth=linewidth,
|
133
|
+
)
|
134
|
+
ax.plot(
|
135
|
+
[x2 - np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
136
|
+
[
|
137
|
+
y_loc - np.abs(np.diff(ylim)) * tailindicator[1],
|
138
|
+
y_loc - np.abs(np.diff(ylim)) * 0.03,
|
139
|
+
],
|
140
|
+
linestyle=linestyle,
|
141
|
+
color=linecolor,
|
142
|
+
linewidth=linewidth,
|
143
|
+
)
|
144
|
+
else:
|
145
|
+
ax.plot(
|
146
|
+
[x1 + np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
147
|
+
[
|
148
|
+
np.min(ylim)
|
149
|
+
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
150
|
+
- np.abs(np.diff(ylim)) * 0.002,
|
151
|
+
np.min(ylim)
|
152
|
+
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
153
|
+
- np.abs(np.diff(ylim)) * 0.002,
|
154
|
+
],
|
155
|
+
linestyle=linestyle,
|
156
|
+
color=linecolor,
|
157
|
+
linewidth=linewidth,
|
158
|
+
)
|
159
|
+
# vertical line
|
160
|
+
ax.plot(
|
161
|
+
[x1 + np.abs(np.diff(xlim)) * 0.01, x1 + np.abs(np.diff(xlim)) * 0.01],
|
162
|
+
[
|
163
|
+
np.min(ylim)
|
164
|
+
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
165
|
+
- np.abs(np.diff(ylim)) * tailindicator[0],
|
166
|
+
np.min(ylim)
|
167
|
+
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
168
|
+
- np.abs(np.diff(ylim)) * 0.002,
|
169
|
+
],
|
170
|
+
linestyle=linestyle,
|
171
|
+
color=linecolor,
|
172
|
+
linewidth=linewidth,
|
173
|
+
)
|
174
|
+
ax.plot(
|
175
|
+
[x2 - np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
|
176
|
+
[
|
177
|
+
np.min(ylim)
|
178
|
+
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
179
|
+
- np.abs(np.diff(ylim)) * tailindicator[1],
|
180
|
+
np.min(ylim)
|
181
|
+
+ 0.95 * (np.max(ylim) - np.min(ylim))
|
182
|
+
- np.abs(np.diff(ylim)) * 0.002,
|
183
|
+
],
|
184
|
+
linestyle=linestyle,
|
185
|
+
color=linecolor,
|
186
|
+
linewidth=linewidth,
|
187
|
+
)
|
184
188
|
if values_below is not None:
|
185
|
-
|
189
|
+
ax.text(
|
186
190
|
xcenter,
|
187
191
|
y_loc * (-0.1),
|
188
192
|
values_below,
|
@@ -194,7 +198,7 @@ def FuncStars(
|
|
194
198
|
)
|
195
199
|
# report / comments
|
196
200
|
if report is not None:
|
197
|
-
|
201
|
+
ax.text(
|
198
202
|
xcenter,
|
199
203
|
report_loc,
|
200
204
|
report,
|
@@ -261,7 +265,7 @@ def FuncCmpt(x1, x2, pmc="auto", pair="unpaired", verbose=True):
|
|
261
265
|
x1, x2, center="median", proportiontocut=0.05
|
262
266
|
)
|
263
267
|
VarType = True if pval_lev > 0.05 and nX1 == nX2 else False
|
264
|
-
print(pair)
|
268
|
+
# print(pair)
|
265
269
|
if "np" in pair: # 'unpaired'
|
266
270
|
if VarType and Normality:
|
267
271
|
# The independent t-test requires that the dependent variable is approximately normally
|
@@ -278,7 +282,7 @@ def FuncCmpt(x1, x2, pmc="auto", pair="unpaired", verbose=True):
|
|
278
282
|
)
|
279
283
|
notes_stat = "unpaired t test"
|
280
284
|
notes_APA = (
|
281
|
-
f"t({nX1+nX2-2})={round(stat_value,
|
285
|
+
f"t({nX1+nX2-2})={round(stat_value,3)},p={round(pval,3)}"
|
282
286
|
)
|
283
287
|
else:
|
284
288
|
# If the Levene's Test for Equality of Variances is statistically significant,
|
@@ -297,7 +301,7 @@ def FuncCmpt(x1, x2, pmc="auto", pair="unpaired", verbose=True):
|
|
297
301
|
notes_stat = "Welchs t-test"
|
298
302
|
# note: APA FORMAT
|
299
303
|
notes_APA = (
|
300
|
-
f"t({nX1+nX2-2})={round(stat_value,
|
304
|
+
f"t({nX1+nX2-2})={round(stat_value,3)},p={round(pval,3)}"
|
301
305
|
)
|
302
306
|
elif "pa" in pair and "np" not in pair: # 'paired'
|
303
307
|
# the paired-samples t-test is considered “robust” in handling violations of normality
|
@@ -309,7 +313,7 @@ def FuncCmpt(x1, x2, pmc="auto", pair="unpaired", verbose=True):
|
|
309
313
|
notes_stat = "paired t test"
|
310
314
|
# note: APA FORMAT
|
311
315
|
notes_APA = (
|
312
|
-
f"t({sum([nX1-1])})={round(stat_value,
|
316
|
+
f"t({sum([nX1-1])})={round(stat_value,3)},p={round(pval,3)}"
|
313
317
|
)
|
314
318
|
elif cfg_pmc == "non-parametric":
|
315
319
|
if "np" in pair: # Perform Mann-Whitney
|
@@ -318,18 +322,18 @@ def FuncCmpt(x1, x2, pmc="auto", pair="unpaired", verbose=True):
|
|
318
322
|
)
|
319
323
|
notes_stat = "Mann-Whitney U"
|
320
324
|
if nX1 == nX2:
|
321
|
-
notes_APA = f"U(n={nX1})={round(stat_value,
|
325
|
+
notes_APA = f"U(n={nX1})={round(stat_value,3)},p={round(pval,3)}"
|
322
326
|
else:
|
323
|
-
notes_APA = f"U(n1={nX1},n2={nX2})={round(stat_value,
|
327
|
+
notes_APA = f"U(n1={nX1},n2={nX2})={round(stat_value,3)},p={round(pval,3)}"
|
324
328
|
elif "pa" in pair and "np" not in pair: # Wilcoxon signed-rank test
|
325
329
|
stat_value, pval = stats.wilcoxon(
|
326
330
|
x1, x2, method="exact", nan_policy="omit"
|
327
331
|
)
|
328
332
|
notes_stat = "Wilcoxon signed-rank"
|
329
333
|
if nX1 == nX2:
|
330
|
-
notes_APA = f"Z(n={nX1})={round(stat_value,
|
334
|
+
notes_APA = f"Z(n={nX1})={round(stat_value,3)},p={round(pval,3)}"
|
331
335
|
else:
|
332
|
-
notes_APA = f"Z(n1={nX1},n2={nX2})={round(stat_value,
|
336
|
+
notes_APA = f"Z(n1={nX1},n2={nX2})={round(stat_value,3)},p={round(pval,3)}"
|
333
337
|
|
334
338
|
# filling output
|
335
339
|
output["stat"] = stat_value
|
@@ -383,7 +387,7 @@ def FuncCmpt(x1, x2, pmc="auto", pair="unpaired", verbose=True):
|
|
383
387
|
# =============================================================================
|
384
388
|
|
385
389
|
|
386
|
-
def str_mean_sem(data: list, delimit=
|
390
|
+
def str_mean_sem(data: list, delimit=3):
|
387
391
|
mean_ = np.nanmean(data)
|
388
392
|
sem_ = np.nanstd(data, ddof=1) / np.sqrt(sum(~np.isnan(data)))
|
389
393
|
return str(round(mean_, delimit)) + "±" + str(round(sem_, delimit))
|
@@ -404,6 +408,7 @@ def FuncMultiCmpt(
|
|
404
408
|
subject=None,
|
405
409
|
group=None,
|
406
410
|
verbose=True,
|
411
|
+
post_hoc=False
|
407
412
|
):
|
408
413
|
if group is None:
|
409
414
|
group = factor
|
@@ -515,12 +520,12 @@ def FuncMultiCmpt(
|
|
515
520
|
if "np" in cfg_pair: # 'unpaired'
|
516
521
|
res_tab = run_kruskal(data, dv, factor)
|
517
522
|
notes_stat = f"Non-parametric Kruskal: {data[factor].nunique()} Way ANOVA"
|
518
|
-
notes_APA = f'H({res_tab.ddof1[0]},
|
523
|
+
notes_APA = [f'H({res_tab.ddof1[0]},N={data.shape[0]})={round(res_tab.H[0],3)},p={round(res_tab["p-unc"][0],3)}']
|
519
524
|
|
520
525
|
elif "pa" in cfg_pair and "np" not in cfg_pair: # 'paired'
|
521
526
|
res_tab = run_friedman(data, dv, factor, subject, method="chisq")
|
522
527
|
notes_stat = f"Non-parametric {data[factor].nunique()} Way Friedman repeated measures ANOVA"
|
523
|
-
notes_APA = f'X^2({res_tab.ddof1[0]})={round(res_tab.Q[0],
|
528
|
+
notes_APA = [f'X^2({res_tab.ddof1[0]})={round(res_tab.Q[0],3)},p={round(res_tab["p-unc"][0],3)}']
|
524
529
|
|
525
530
|
# =============================================================================
|
526
531
|
# # Post-hoc
|
@@ -535,7 +540,10 @@ def FuncMultiCmpt(
|
|
535
540
|
go_mix_between = None if ("pa" in cfg_pair) or ("np" not in cfg_pair) else factor
|
536
541
|
go_mix_within = within if ("mix" in cfg_pair) or ("both" in cfg_pair) else None
|
537
542
|
go_mix_within = factor if ("pa" in cfg_pair) or ("np" not in cfg_pair) else None
|
543
|
+
|
538
544
|
if res_tab["p-unc"][0] <= 0.05:
|
545
|
+
post_hoc=True
|
546
|
+
if post_hoc:
|
539
547
|
# Pairwise Comparisons
|
540
548
|
method_post_hoc = [
|
541
549
|
"bonf", # 'bonferroni', # : one-step correction
|
@@ -602,7 +610,10 @@ def FuncMultiCmpt(
|
|
602
610
|
# # filling output
|
603
611
|
# =============================================================================
|
604
612
|
|
605
|
-
pd.set_option(
|
613
|
+
pd.set_option('display.max_columns', None) # Show all columns
|
614
|
+
pd.set_option('display.max_colwidth', None) # No limit on column width
|
615
|
+
pd.set_option('display.expand_frame_repr', False) # Prevent line-wrapping
|
616
|
+
|
606
617
|
output["stat"] = notes_stat
|
607
618
|
# print(output['APA'])
|
608
619
|
output["APA"] = notes_APA
|
@@ -616,21 +627,21 @@ def FuncMultiCmpt(
|
|
616
627
|
def display_output(output: dict):
|
617
628
|
if isinstance(output, pd.DataFrame):
|
618
629
|
output = output.to_dict(orient="list")
|
619
|
-
# ['res_posthoc', 'stat', 'APA', 'pval', 'res_tab']
|
620
|
-
|
621
|
-
#
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
except:
|
626
|
-
|
630
|
+
# ['res_posthoc', 'stat', 'APA', 'pval', 'res_tab']
|
631
|
+
|
632
|
+
# ? show APA
|
633
|
+
# print(f"\n\ndisplay stat_output")
|
634
|
+
# try:
|
635
|
+
# print(f"APA: {output["APA"]}")
|
636
|
+
# except:
|
637
|
+
# pass
|
627
638
|
try:
|
628
|
-
print("
|
639
|
+
print("stats table: ⤵")
|
629
640
|
display(output["res_tab"])
|
630
641
|
except:
|
631
642
|
pass
|
632
643
|
try:
|
633
|
-
print("
|
644
|
+
print(f"APA ⤵\n{output["APA"][0]} ⤵\npost-hoc analysis ⤵")
|
634
645
|
display(output["res_posthoc"])
|
635
646
|
except:
|
636
647
|
pass
|
@@ -692,17 +703,19 @@ def extract_apa(res_tab):
|
|
692
703
|
notes_APA = []
|
693
704
|
if "ddof1" in res_tab:
|
694
705
|
for irow in range(res_tab.shape[0]):
|
695
|
-
note_tmp = f'{res_tab.Source[irow]}:F{round(res_tab.ddof1[irow]),round(res_tab.ddof2[irow])}={round(res_tab.F[irow],
|
696
|
-
notes_APA.append(
|
706
|
+
note_tmp = f'{res_tab.Source[irow]}:F{round(res_tab.ddof1[irow]),round(res_tab.ddof2[irow])}={round(res_tab.F[irow],3)},p={round(res_tab["p-unc"][irow],3)}'
|
707
|
+
notes_APA.append(note_tmp)
|
697
708
|
elif "DF" in res_tab:
|
709
|
+
print("here")
|
710
|
+
display(res_tab)
|
698
711
|
for irow in range(res_tab.shape[0] - 1):
|
699
|
-
note_tmp = f'{res_tab.Source[irow]}:F{round(res_tab.DF[irow]),round(res_tab.DF[res_tab.shape[0]-1])}={round(res_tab.F[irow],
|
700
|
-
notes_APA.append(
|
701
|
-
notes_APA.append(
|
712
|
+
note_tmp = f'{res_tab.Source[irow]}:F{round(res_tab.DF[irow]),round(res_tab.DF[res_tab.shape[0]-1])}={round(res_tab.F[irow],3)},p={round(res_tab["p-unc"][irow],3)}'
|
713
|
+
notes_APA.append(note_tmp)
|
714
|
+
notes_APA.append(np.nan)
|
702
715
|
elif "DF1" in res_tab: # in 'mix' case
|
703
716
|
for irow in range(res_tab.shape[0]):
|
704
|
-
note_tmp = f'{res_tab.Source[irow]}:F{round(res_tab.DF1[irow]),round(res_tab.DF2[irow])}={round(res_tab.F[irow],
|
705
|
-
notes_APA.append(
|
717
|
+
note_tmp = f'{res_tab.Source[irow]}:F{round(res_tab.DF1[irow]),round(res_tab.DF2[irow])}={round(res_tab.F[irow],3)},p={round(res_tab["p-unc"][irow],3)}'
|
718
|
+
notes_APA.append(note_tmp)
|
706
719
|
return notes_APA
|
707
720
|
|
708
721
|
|
@@ -856,220 +869,7 @@ def df_wide_long(df):
|
|
856
869
|
elif rows > columns:
|
857
870
|
return "Long"
|
858
871
|
|
859
|
-
|
860
|
-
# =============================================================================
|
861
|
-
# # One-way ANOVA
|
862
|
-
# =============================================================================
|
863
|
-
# url = "http://stats191.stanford.edu/data/rehab.csv"
|
864
|
-
# rehab_table = pd.read_table(url, delimiter=",")
|
865
|
-
# rehab_table.to_csv("rehab.table")
|
866
|
-
# fig, ax = plt.subplots(figsize=(8, 6))
|
867
|
-
# fig = rehab_table.boxplot("Time", "Fitness", ax=ax, grid=False)
|
868
|
-
# # fig, ax = plt.subplots(figsize=(8, 6))
|
869
|
-
# # set_pub()
|
870
|
-
# # sns.boxenplot(x="Time",y="Fitness",data = rehab_table)
|
871
|
-
|
872
|
-
# out2 = FuncMultiCmpt(pmc='pmc', pair='unpair',
|
873
|
-
# data=rehab_table, dv='Time', factor='Fitness')
|
874
|
-
# # print(out2['res_tab'])
|
875
|
-
# # print(out2['APA'])
|
876
|
-
# out2['res_posthoc']
|
877
|
-
# out2['res_posthoc']['p-unc'][0]
|
878
|
-
# out2['res_posthoc']['p-adjust'][0]
|
879
|
-
# out2['res_posthoc']['p-corr'][0]
|
880
|
-
|
881
|
-
|
882
|
-
# =============================================================================
|
883
|
-
# # Interactions and ANOVA
|
884
|
-
# https://www.statsmodels.org/dev/examples/notebooks/generated/interactions_anova.html
|
885
|
-
# url = "http://stats191.stanford.edu/data/salary.table"
|
886
|
-
# fh = urlopen(url)
|
887
|
-
# df = pd.read_table(fh)
|
888
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='unpaired', data=df,
|
889
|
-
# dv='S', factor=['X', 'E', 'M'], group='M')
|
890
|
-
# # # two-way anova
|
891
|
-
# # https://www.statology.org/two-way-anova-python/
|
892
|
-
# # =============================================================================
|
893
|
-
# # df = pd.DataFrame({'water': np.repeat(['daily', 'weekly'], 15),
|
894
|
-
# # 'sun': np.tile(np.repeat(['low', 'med', 'high'], 5), 2),
|
895
|
-
# # 'height': [6, 6, 6, 5, 6, 5, 5, 6, 4, 5,
|
896
|
-
# # 6, 6, 7, 8, 7, 3, 4, 4, 4, 5,
|
897
|
-
# # 4, 4, 4, 4, 4, 5, 6, 6, 7, 8]})
|
898
|
-
# # out1 = FuncMultiCmpt(pmc='pmc', pair='unpaired', data=df,
|
899
|
-
# # dv='height', factor=['water','sun'],group='water')
|
900
|
-
|
901
|
-
|
902
|
-
# =============================================================================
|
903
|
-
# # two way anova
|
904
|
-
# https://www.geeksforgeeks.org/how-to-perform-a-two-way-anova-in-python/
|
905
|
-
# =============================================================================
|
906
|
-
# df1=pd.DataFrame({'Fertilizer': np.repeat(['daily', 'weekly'], 15),
|
907
|
-
# 'Watering': np.repeat(['daily', 'weekly'], 15),
|
908
|
-
# 'height': [14, 16, 15, 15, 16, 13, 12, 11,
|
909
|
-
# 14, 15, 16, 16, 17, 18, 14, 13,
|
910
|
-
# 14, 14, 14, 15, 16, 16, 17, 18,
|
911
|
-
# 14, 13, 14, 14, 14, 15]})
|
912
|
-
|
913
|
-
# df1['subject'] = np.tile(range(0, 15), (1, 2)).T
|
914
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='unpaired', data=df1,
|
915
|
-
# dv='height', factor=['Fertilizer','Watering'],group='Watering')
|
916
|
-
# # print(out1['stat'])
|
917
|
-
# # print(out1['res_tab'])
|
918
|
-
|
919
|
-
# =============================================================================
|
920
|
-
# # welch anova
|
921
|
-
# https://www.geeksforgeeks.org/how-to-perform-welchs-anova-in-python/
|
922
|
-
# =============================================================================
|
923
|
-
# df = pd.DataFrame({'score': [64, 66, 68, 75, 78, 94, 98, 79, 71, 80,
|
924
|
-
# 91, 92, 93, 90, 97, 94, 82, 88, 95, 96,
|
925
|
-
# 79, 78, 88, 94, 92, 85, 83, 85, 82, 81],
|
926
|
-
# 'group': np.repeat(['strat1', 'strat2', 'strat3'],repeats=10)})
|
927
|
-
# out1 = FuncMultiCmpt(pmc='auto',pair='unpaired',data=df, dv='score', factor='group', group='group')
|
928
|
-
# =============================================================================
|
929
|
-
# # two way anova
|
930
|
-
# https://www.statology.org/two-way-anova-python/
|
931
|
-
# =============================================================================
|
932
|
-
# df = pd.DataFrame({'water': np.repeat(['daily', 'weekly'], 15),
|
933
|
-
# 'sun': np.tile(np.repeat(['low', 'med', 'high'], 5), 2),
|
934
|
-
# 'height': [6, 6, 6, 5, 6, 5, 5, 6, 4, 5,
|
935
|
-
# 6, 6, 7, 8, 7, 3, 4, 4, 4, 5,
|
936
|
-
# 4, 4, 4, 4, 4, 5, 6, 6, 7, 8]})
|
937
|
-
# df['subject'] = np.tile(range(0, 15), (1, 2)).T
|
938
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='unpaired', data=df,
|
939
|
-
# dv='height', factor=['water', 'sun'], subject='subject', group='water')
|
940
|
-
# # print(out1['stat'])
|
941
|
-
# # print(out1['res_tab'])
|
942
|
-
|
943
|
-
# =============================================================================
|
944
|
-
# # 3-way ANOVA
|
945
|
-
# =============================================================================
|
946
|
-
# df = pd.DataFrame({'program': np.repeat([1, 2], 20),
|
947
|
-
# 'gender': np.tile(np.repeat(['M', 'F'], 10), 2),
|
948
|
-
# 'division': np.tile(np.repeat([1, 2], 5), 4),
|
949
|
-
# 'height': [7, 7, 8, 8, 7, 6, 6, 5, 6, 5,
|
950
|
-
# 5, 5, 4, 5, 4, 3, 3, 4, 3, 3,
|
951
|
-
# 6, 6, 5, 4, 5, 4, 5, 4, 4, 3,
|
952
|
-
# 2, 2, 1, 4, 4, 2, 1, 1, 2, 1]})
|
953
|
-
# df['subject'] = np.tile(range(0, 20), (1, 2)).T
|
954
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='unpaired', data=df,
|
955
|
-
# dv='height', factor=['gender', 'program', 'division'], subject='subject', group='program')
|
956
|
-
# # print(out1['stat'])
|
957
|
-
# # print(out1['res_tab'])
|
958
|
-
|
959
|
-
# =============================================================================
|
960
|
-
# # Repeated Measures ANOVA in Python
|
961
|
-
# =============================================================================
|
962
|
-
# df = pd.DataFrame({'patient': np.repeat([1, 2, 3, 4, 5], 4),
|
963
|
-
# 'drug': np.tile([1, 2, 3, 4], 5),
|
964
|
-
# 'response': [30, 28, 16, 34,
|
965
|
-
# 14, 18, 10, 22,
|
966
|
-
# 24, 20, 18, 30,
|
967
|
-
# 38, 34, 20, 44,
|
968
|
-
# 26, 28, 14, 30]})
|
969
|
-
# # df['subject'] = np.tile(range(0, 20), (1, 2)).T
|
970
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='paired', data=df,
|
971
|
-
# dv='response', factor=['drug'], subject='patient', group='drug')
|
972
|
-
# print(out1['stat'])
|
973
|
-
# print(out1['res_tab'])
|
974
|
-
# print(out1['APA'])
|
975
|
-
|
976
|
-
# =============================================================================
|
977
|
-
# # repeated anova
|
978
|
-
# https://www.geeksforgeeks.org/how-to-perform-a-repeated-measures-anova-in-python/
|
979
|
-
# =============================================================================
|
980
|
-
# df = pd.DataFrame({'Cars': np.repeat([1, 2, 3, 4, 5], 4),
|
981
|
-
# 'Engine Oil': np.tile([1, 2, 3, 4], 5),
|
982
|
-
# 'Mileage': [36, 38, 30, 29,
|
983
|
-
# 34, 38, 30, 29,
|
984
|
-
# 34, 28, 38, 32,
|
985
|
-
# 38, 34, 20, 44,
|
986
|
-
# 26, 28, 34, 50]})
|
987
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='paired', data=df,
|
988
|
-
# dv='Mileage', factor=['Engine Oil'], subject='Cars', group='Cars')
|
989
|
-
# =============================================================================
|
990
|
-
# #two-way repeated anova
|
991
|
-
# =============================================================================
|
992
|
-
# df = pd.read_csv(
|
993
|
-
# "https://reneshbedre.github.io/assets/posts/anova/plants_leaves_two_within.csv")
|
994
|
-
# df
|
995
|
-
# # df['subject'] = np.tile(range(0, 20), (1, 2)).T
|
996
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='paired', data=df,
|
997
|
-
# dv='num_leaves', factor=['year', 'time'], subject='plants', group='year')
|
998
|
-
# print(out1['stat'])
|
999
|
-
# print(out1['res_tab'])
|
1000
|
-
# print(out1['APA'])
|
1001
|
-
|
1002
|
-
# =============================================================================
|
1003
|
-
# # repeated anova
|
1004
|
-
# =============================================================================
|
1005
|
-
# df = pd.read_csv('/Users/macjianfeng/Desktop/test.csv')
|
1006
|
-
# df.head()
|
1007
|
-
# df.loc[df['animal'].str.contains('Sleep'), 'experiment'] = 'sleep'
|
1008
|
-
# df.loc[df['animal'].str.contains('Wake'), 'experiment'] = 'wake'
|
1009
|
-
# df.loc[df['variable'].str.contains('hypo'), 'region'] = 'hypo'
|
1010
|
-
# df.loc[df['variable'].str.contains('cort'), 'region'] = 'cort'
|
1011
|
-
# df
|
1012
|
-
# for i in range(4):
|
1013
|
-
# match i:
|
1014
|
-
# case 0:
|
1015
|
-
# prot_name = 'A1'
|
1016
|
-
# case 1:
|
1017
|
-
# prot_name = 'A2'
|
1018
|
-
# case 2:
|
1019
|
-
# prot_name = '845'
|
1020
|
-
# case 3:
|
1021
|
-
# prot_name = '831'
|
1022
|
-
# df_tmp = df[df["variable"].str.contains(prot_name)]
|
1023
|
-
# df_tmp['protein'] = prot_name
|
1024
|
-
# df_tmp = df_tmp.reset_index()
|
1025
|
-
# print(df_tmp)
|
1026
|
-
|
1027
|
-
# out1 = FuncMultiCmpt(pmc='pmc', pair='mix', data=df_tmp,
|
1028
|
-
# dv='value', between='experiment', within='region', subject='animal', group='experiment')
|
1029
|
-
# print(out1['stat'])
|
1030
|
-
# print(out1['res_tab'])
|
1031
|
-
# # =============================================================================
|
1032
|
-
# One-way ANOVA
|
1033
|
-
# df1 = pd.read_csv('/Users/macjianfeng/Desktop/Book2.csv')
|
1034
|
-
# df2 = df1.melt()
|
1035
|
-
# out1 = FuncMultiCmpt(pmc='npmc', pair='unpaired', data=df2,
|
1036
|
-
# dv='libido', factor=['brand x', 'brand y', 'brand z'], subject='participant')
|
1037
|
-
# print(out1['stat'])
|
1038
|
-
# print(out1['res_tab'])
|
1039
|
-
# =============================================================================
|
1040
|
-
|
1041
|
-
|
1042
|
-
# =============================================================================
|
1043
|
-
# # #One-way ANOVA new example: https://www.pythonfordatascience.org/anova-python/
|
1044
|
-
# =============================================================================
|
1045
|
-
# df1 = pd.read_csv(
|
1046
|
-
# "https://raw.githubusercontent.com/researchpy/Data-sets/master/difficile.csv")
|
1047
|
-
# df1.drop('person', axis=1, inplace=True)
|
1048
|
-
# # Recoding value from numeric to string
|
1049
|
-
# df1['dose'].replace({1: 'placebo', 2: 'low', 3: 'high'}, inplace=True)
|
1050
|
-
# df1.head(10)
|
1051
|
-
|
1052
|
-
# out3= FuncMultiCmpt(pmc='pmc', data=df1, dv='libido', factor='dose')
|
1053
|
-
# # print(out3['res_tab'])
|
1054
|
-
# # # print(out3['res_posthoc'])
|
1055
|
-
# # print(out3['APA'])
|
1056
|
-
|
1057
|
-
# =============================================================================
|
1058
|
-
# https://lifewithdata.com/2023/06/08/how-to-perform-a-two-way-anova-in-python/
|
1059
|
-
# =============================================================================
|
1060
|
-
# data = {
|
1061
|
-
# 'Diet': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C'],
|
1062
|
-
# 'Workout': ['Low', 'Medium', 'High', 'Low', 'Medium', 'High', 'Low', 'Medium', 'High', 'Low', 'Medium', 'High'],
|
1063
|
-
# 'WeightLoss': [3, 4, 5, 3.2, 5, 6, 5.2, 6, 5.5, 4, 5.5, 6.2]
|
1064
|
-
# }
|
1065
|
-
# df = pd.DataFrame(data)
|
1066
|
-
# out4= FuncMultiCmpt(pmc='pmc', pair='unpaired',data=df, dv='WeightLoss', factor=['Diet','Workout'],group='Diet')
|
1067
|
-
|
1068
|
-
# =============================================================================
|
1069
|
-
# # convert to list to string
|
1070
|
-
# =============================================================================
|
1071
|
-
|
1072
|
-
|
872
|
+
|
1073
873
|
def sort_rows_move_nan(arr, sort=False):
|
1074
874
|
# Handle edge cases where all values are NaN
|
1075
875
|
if np.all(np.isnan(arr)):
|
@@ -1106,11 +906,11 @@ def sort_rows_move_nan(arr, sort=False):
|
|
1106
906
|
return clean_arr_
|
1107
907
|
|
1108
908
|
|
1109
|
-
def df2array(data: pd.DataFrame, x, y, hue=None, sort=False):
|
909
|
+
def df2array(data: pd.DataFrame, x=None, y=None, hue=None, sort=False):
|
1110
910
|
if hue is None:
|
1111
911
|
a = []
|
1112
912
|
if sort:
|
1113
|
-
np.sort(data[x].unique().tolist()).tolist()
|
913
|
+
cat_x=np.sort(data[x].unique().tolist()).tolist()
|
1114
914
|
else:
|
1115
915
|
cat_x = data[x].unique().tolist()
|
1116
916
|
for i, x_ in enumerate(cat_x):
|
@@ -1131,7 +931,17 @@ def df2array(data: pd.DataFrame, x, y, hue=None, sort=False):
|
|
1131
931
|
a = padcat(a, new_, axis=0)
|
1132
932
|
return sort_rows_move_nan(a).T
|
1133
933
|
|
1134
|
-
|
934
|
+
def array2df(data: np.ndarray):
|
935
|
+
df = pd.DataFrame()
|
936
|
+
df["group"] = (
|
937
|
+
np.tile(
|
938
|
+
["group" + str(i) for i in range(1, data.shape[1] + 1)], [data.shape[0], 1]
|
939
|
+
)
|
940
|
+
.reshape(-1, 1, order="F")[:, 0]
|
941
|
+
.tolist()
|
942
|
+
)
|
943
|
+
df["value"] = data.reshape(-1, 1, order="F")
|
944
|
+
return df
|
1135
945
|
def padcat(*args, fill_value=np.nan, axis=1, order="row"):
|
1136
946
|
"""
|
1137
947
|
Concatenate vectors with padding.
|