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.
Files changed (50) hide show
  1. py2ls/.DS_Store +0 -0
  2. py2ls/.git/COMMIT_EDITMSG +1 -1
  3. py2ls/.git/FETCH_HEAD +1 -1
  4. py2ls/.git/index +0 -0
  5. py2ls/.git/logs/HEAD +1 -0
  6. py2ls/.git/logs/refs/heads/main +1 -0
  7. py2ls/.git/logs/refs/remotes/origin/HEAD +2 -0
  8. py2ls/.git/logs/refs/remotes/origin/main +1 -0
  9. py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
  10. py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
  11. py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
  12. py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
  13. py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
  14. py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
  15. py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
  16. py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
  17. py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
  18. py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +2 -0
  19. py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
  20. py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
  21. py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
  22. py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
  23. py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +5 -0
  24. py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
  25. py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +3 -0
  26. py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
  27. py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
  28. py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
  29. py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
  30. py2ls/.git/refs/heads/main +1 -1
  31. py2ls/.git/refs/remotes/origin/main +1 -1
  32. py2ls/data/styles/example/style1.pdf +0 -0
  33. py2ls/data/styles/example/style2.pdf +0 -0
  34. py2ls/data/styles/example/style3.pdf +0 -0
  35. py2ls/data/styles/example/style4.pdf +0 -0
  36. py2ls/data/styles/example/style5.pdf +0 -0
  37. py2ls/data/styles/example/style6.pdf +0 -0
  38. py2ls/data/styles/example/style7.pdf +0 -0
  39. py2ls/data/styles/example/style8.pdf +0 -0
  40. py2ls/data/styles/example/style9.pdf +0 -0
  41. py2ls/data/styles/style6.json +31 -20
  42. py2ls/data/styles/style7.json +201 -0
  43. py2ls/data/styles/style8.json +199 -0
  44. py2ls/data/styles/style9.json +215 -0
  45. py2ls/netfinder.py +0 -8
  46. py2ls/plot.py +561 -126
  47. py2ls/stats.py +182 -372
  48. {py2ls-0.1.9.3.dist-info → py2ls-0.1.9.5.dist-info}/METADATA +1 -1
  49. {py2ls-0.1.9.3.dist-info → py2ls-0.1.9.5.dist-info}/RECORD +50 -17
  50. {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.06, 0.06],
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
- # ns / *
56
- if alpha < pval:
57
- if nsshow == "on":
58
- ns_str = f"p={round(pval, 3)}" if pval < 0.9 else "ns"
59
- color = "m" if pval < 0.1 else "k"
60
- plt.text(
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
- ns_str,
80
+ symbol,
64
81
  ha="center",
65
- va="bottom", # 'center_baseline',
66
- fontsize=fontsize - 6 if fontsize > 6 else fontsize,
82
+ va="top",#"center_baseline",
83
+ fontsize=fontsize,
67
84
  fontname=fontname,
68
- color=color,
69
- rotation=rotation,
70
- # bbox=dict(facecolor=None, edgecolor=None, color=None, linewidth=None)
85
+ color=symbolcolor,
71
86
  )
72
- elif 0.01 < pval <= alpha:
73
- plt.text(
74
- xcenter,
75
- y_loc,
76
- symbol,
77
- ha="center",
78
- va="center_baseline",
79
- fontsize=fontsize,
80
- fontname=fontname,
81
- color=symbolcolor,
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
- plt.plot(
171
- [x2 - np.abs(np.diff(xlim)) * 0.01, x2 - np.abs(np.diff(xlim)) * 0.01],
172
- [
173
- np.min(ylim)
174
- + 0.95 * (np.max(ylim) - np.min(ylim))
175
- - np.abs(np.diff(ylim)) * tailindicator[1],
176
- np.min(ylim)
177
- + 0.95 * (np.max(ylim) - np.min(ylim))
178
- - np.abs(np.diff(ylim)) * 0.002,
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
- plt.text(
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
- plt.text(
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, 5)},p={round(pval, 5)}"
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, 5)},p={round(pval, 5)}"
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, 5)},p={round(pval, 5)}"
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, 5)},p={round(pval, 5)}"
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, 5)},p={round(pval, 5)}"
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, 5)},p={round(pval, 5)}"
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, 5)},p={round(pval, 5)}"
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=5):
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]},n={data.shape[0]})={round(res_tab.H[0], 5)},p={round(res_tab["p-unc"][0], 5)}'
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], 5)},p={round(res_tab["p-unc"][0], 5)}'
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("display.max_columns", None)
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
- # res_keys = list(output.keys())
621
- # display(res_keys)
622
- try:
623
- print("APA:")
624
- display(output["APA"])
625
- except:
626
- pass
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("results table:")
639
+ print("stats table:")
629
640
  display(output["res_tab"])
630
641
  except:
631
642
  pass
632
643
  try:
633
- print("posthoc:")
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], 5)},p={round(res_tab["p-unc"][irow], 5)}'
696
- notes_APA.append([note_tmp])
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], 5)},p={round(res_tab["p-unc"][irow], 5)}'
700
- notes_APA.append([note_tmp])
701
- notes_APA.append(["NaN"])
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], 5)},p={round(res_tab["p-unc"][irow], 5)}'
705
- notes_APA.append([note_tmp])
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.