Skip to content

Commit 0de21ff

Browse files
committed
change plot style and others
1 parent 8a47196 commit 0de21ff

26 files changed

Lines changed: 94 additions & 52 deletions

dabest/_classes.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,7 @@ def __init__(self, control, test, effect_size,proportional,
18451845
is_paired,
18461846
permutation_count)
18471847

1848-
if is_paired:
1848+
if is_paired and proportional is False:
18491849
# Wilcoxon, a non-parametric version of the paired T-test.
18501850
wilcoxon = spstats.wilcoxon(control, test)
18511851
self.__pvalue_wilcoxon = wilcoxon.pvalue
@@ -1869,6 +1869,21 @@ def __init__(self, control, test, effect_size,proportional,
18691869
# len(control),
18701870
# alpha=self.__alpha)
18711871

1872+
elif is_paired and proportional is True:
1873+
# for binary paired data, use McNemar's test
1874+
# References:
1875+
# https://en.wikipedia.org/wiki/McNemar%27s_test
1876+
from statsmodels.stats.contingency_tables import mcnemar
1877+
import pandas as pd
1878+
df_temp = pd.DataFrame({'control': control, 'test': test})
1879+
x1 = len(df_temp[(df_temp['control'] == 0)&(df_temp['test'] == 0)])
1880+
x2 = len(df_temp[(df_temp['control'] == 0)&(df_temp['test'] == 1)])
1881+
x3 = len(df_temp[(df_temp['control'] == 1)&(df_temp['test'] == 0)])
1882+
x4 = len(df_temp[(df_temp['control'] == 1)&(df_temp['test'] == 1)])
1883+
table = [[x1,x2],[x3,x4]]
1884+
_mcnemar = mcnemar(table, exact=True, correction=True)
1885+
self.__pvalue_mcnemar = _mcnemar.pvalue
1886+
self.__statistic_mcnemar = _mcnemar.statistic
18721887

18731888
elif effect_size == "cliffs_delta":
18741889
# Let's go with Brunner-Munzel!
@@ -2183,6 +2198,22 @@ def statistic_wilcoxon(self):
21832198
except AttributeError:
21842199
return npnan
21852200

2201+
@property
2202+
def pvalue_mcnemar(self):
2203+
from numpy import nan as npnan
2204+
try:
2205+
return self.__pvalue_mcnemar
2206+
except AttributeError:
2207+
return npnan
2208+
2209+
@property
2210+
def statistic_mcnemar(self):
2211+
from numpy import nan as npnan
2212+
try:
2213+
return self.__statistic_mcnemar
2214+
except AttributeError:
2215+
return npnan
2216+
21862217

21872218

21882219
@property
@@ -2504,6 +2535,9 @@ def __pre_calc(self):
25042535
'pvalue_wilcoxon',
25052536
'statistic_wilcoxon',
25062537

2538+
'pvalue_mcnemar',
2539+
'statistic_mcnemar',
2540+
25072541
'pvalue_paired_students_t',
25082542
'statistic_paired_students_t',
25092543

@@ -2623,8 +2657,9 @@ def plot(self, color_col=None,
26232657
custom_palette=None, swarm_desat=0.5, halfviolin_desat=1,
26242658
halfviolin_alpha=0.8,
26252659

2660+
face_color = None,
26262661
#bar plot
2627-
bar_label=None, bar_desat=0.8, bar_width = 0.5,bar_ylim = None,
2662+
bar_label=None, bar_desat=0.5, bar_width = 0.5,bar_ylim = None,
26282663
# error bar of proportion plot
26292664
ci=None, err_color=None,
26302665

dabest/_stats_tools/effsize.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ def cohens_h(control, test):
253253
'''
254254

255255
import numpy as np
256+
np.seterr(divide='ignore', invalid='ignore')
256257
import pandas as pd
257258

258259
# Check whether dataframe contains only 0s and 1s.

dabest/plotter.py

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
1717
swarm_ylim=None, contrast_ylim=None, delta2_ylim=None,
1818
custom_palette=None, swarm_desat=0.5, halfviolin_desat=1,
1919
halfviolin_alpha=0.8,
20+
face_color = None,
21+
bar_label=None, bar_desat=0.8, bar_width = 0.5,bar_ylim = None,
22+
ci=None, err_color=None,
2023
float_contrast=True,
2124
show_pairs=True,
2225
show_delta2=True,
@@ -34,7 +37,6 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
3437
"""
3538

3639
import numpy as np
37-
np.seterr(divide='ignore', invalid='ignore') # avoid message warnings when plotting
3840
import seaborn as sns
3941
import matplotlib.pyplot as plt
4042
import pandas as pd
@@ -57,7 +59,9 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
5759
plt.rcParams['axes.grid'] = False
5860

5961
ytick_color = plt.rcParams["ytick.color"]
60-
axes_facecolor = plt.rcParams['axes.facecolor']
62+
face_color = plot_kwargs["face_color"]
63+
if plot_kwargs["face_color"] is None:
64+
face_color = "white"
6165

6266
dabest_obj = EffectSizeDataFrame.dabest_obj
6367
plot_data = EffectSizeDataFrame._plot_data
@@ -223,17 +227,24 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
223227
err2 = ' is not a matplotlib palette. Please check.'
224228
raise ValueError(err1 + err2)
225229

226-
swarm_colors = [sns.desaturate(c, swarm_desat) for c in unsat_colors]
227-
plot_palette_raw = dict(zip(names, swarm_colors))
230+
if custom_pal is None and color_col is None:
231+
swarm_colors = [sns.desaturate(c, swarm_desat) for c in unsat_colors]
232+
plot_palette_raw = dict(zip(names.categories, swarm_colors))
228233

229-
bar_desat_desat = bar_desat * 0.1
230-
bar_color = [sns.desaturate(c, bar_desat) for c in unsat_colors]
231-
bar_color_desaturate = [sns.desaturate(c, bar_desat_desat) for c in unsat_colors]
232-
plot_palette_bar1 = dict(zip(names, bar_color_desaturate))
233-
plot_palette_bar2 = dict(zip(names, bar_color))
234+
bar_color = [sns.desaturate(c, bar_desat) for c in unsat_colors]
235+
plot_palette_bar = dict(zip(names.categories, bar_color))
234236

235-
contrast_colors = [sns.desaturate(c, contrast_desat) for c in unsat_colors]
236-
plot_palette_contrast = dict(zip(names, contrast_colors))
237+
contrast_colors = [sns.desaturate(c, contrast_desat) for c in unsat_colors]
238+
plot_palette_contrast = dict(zip(names.categories, contrast_colors))
239+
else:
240+
swarm_colors = [sns.desaturate(c, swarm_desat) for c in unsat_colors]
241+
plot_palette_raw = dict(zip(names, swarm_colors))
242+
243+
bar_color = [sns.desaturate(c, bar_desat) for c in unsat_colors]
244+
plot_palette_bar = dict(zip(names, bar_color))
245+
246+
contrast_colors = [sns.desaturate(c, contrast_desat) for c in unsat_colors]
247+
plot_palette_contrast = dict(zip(names, contrast_colors))
237248

238249
# Infer the figsize.
239250
fig_size = plot_kwargs["fig_size"]
@@ -242,7 +253,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
242253
# Increase the width for delta-delta graph
243254
if show_delta2 or show_mini_meta:
244255
all_groups_count += 2
245-
if is_paired and show_pairs is True:
256+
if is_paired and show_pairs is True and proportional is False:
246257
frac = 0.75
247258
else:
248259
frac = 1
@@ -258,8 +269,8 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
258269

259270
# Initialise the figure.
260271
# sns.set(context="talk", style='ticks')
261-
init_fig_kwargs = dict(figsize=fig_size, dpi=plot_kwargs["dpi"],
262-
tight_layout=True)
272+
init_fig_kwargs = dict(figsize=fig_size, dpi=plot_kwargs["dpi"])
273+
# ,tight_layout=True)
263274

264275
width_ratios_ga = [2.5, 1]
265276
h_space_cummings = 0.3
@@ -272,6 +283,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
272283
ax_position = rawdata_axes.get_position() # [[x0, y0], [x1, y1]]
273284

274285
fig = rawdata_axes.get_figure()
286+
fig.patch.set_facecolor(face_color)
275287

276288
if float_contrast is True:
277289
axins = rawdata_axes.inset_axes(
@@ -314,11 +326,13 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
314326
gridspec_kw={"width_ratios": width_ratios_ga,
315327
"wspace": 0},
316328
**init_fig_kwargs)
329+
fig.patch.set_facecolor(face_color)
317330

318331
else:
319332
fig, axx = plt.subplots(nrows=2,
320333
gridspec_kw={"hspace": 0.3},
321334
**init_fig_kwargs)
335+
fig.patch.set_facecolor(face_color)
322336
# If the contrast axes are NOT floating, create lists to store
323337
# raw ylims and raw tick intervals, so that I can normalize
324338
# their ylims later.
@@ -330,6 +344,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
330344
contrast_axes = axx[1]
331345
rawdata_axes.set_frame_on(False)
332346
contrast_axes.set_frame_on(False)
347+
fig.set_tight_layout(False)
333348

334349
redraw_axes_kwargs = {'colors' : ytick_color,
335350
'facecolors' : ytick_color,
@@ -406,12 +421,12 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
406421
bar1 = sns.barplot(data=bar1_df, x=xvar, y="proportion",
407422
ax=rawdata_axes,
408423
order=all_plot_groups,
409-
palette=plot_palette_bar1,
424+
linewidth=2, facecolor=(1, 1, 1, 0), edgecolor=bar_color,
410425
zorder=1)
411426
bar2 = sns.barplot(data=plot_data, x=xvar, y=yvar,
412427
ax=rawdata_axes,
413428
order=all_plot_groups,
414-
palette=plot_palette_bar2,
429+
palette=plot_palette_bar,
415430
zorder=1,
416431
**barplot_kwargs)
417432
# adjust the width of bars
@@ -457,12 +472,12 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
457472
bar1 = sns.barplot(data=bar1_df, x=xvar, y="proportion",
458473
ax=rawdata_axes,
459474
order=all_plot_groups,
460-
palette=plot_palette_bar1,
475+
linewidth=2, facecolor=(1, 1, 1, 0), edgecolor=bar_color,
461476
zorder=1)
462477
bar2 = sns.barplot(data=plot_data, x=xvar, y=yvar,
463478
ax=rawdata_axes,
464479
order=all_plot_groups,
465-
palette=plot_palette_bar2,
480+
palette=plot_palette_bar,
466481
zorder=1,
467482
**barplot_kwargs)
468483
# adjust the width of bars
@@ -672,7 +687,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
672687
if bootstraps_color_by_group is False:
673688
legend_labels_unique = np.unique(legend_labels)
674689
unique_idx = np.unique(legend_labels, return_index=True)[1]
675-
legend_handles_unique = (pd.Series(legend_handles).loc[unique_idx]).tolist()
690+
legend_handles_unique = (pd.Series(legend_handles,dtype='float64').loc[unique_idx]).tolist()
676691

677692
if len(legend_handles_unique) > 0:
678693
if float_contrast is True:
@@ -739,7 +754,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
739754
contrast_axes.set_ylim(og_ylim_contrast)
740755
contrast_axes.set_xlim(contrast_xlim_max-1, contrast_xlim_max)
741756

742-
elif effect_size_type in ["cohens_d", "hedges_g"]:
757+
elif effect_size_type in ["cohens_d", "hedges_g","cohens_h"]:
743758
if is_paired:
744759
which_std = 1
745760
else:
@@ -761,7 +776,10 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
761776
hg_correction_factor = _compute_hedges_correction_factor(len_control, len_test)
762777

763778
ylim_scale_factor = pooled_sd / hg_correction_factor
764-
779+
780+
elif effect_size_type == "cohens_h":
781+
ylim_scale_factor = (np.mean(temp_test)-np.mean(temp_control))/ difference
782+
765783
else:
766784
ylim_scale_factor = pooled_sd
767785

@@ -794,9 +812,10 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
794812
**reflines_kwargs)
795813

796814
# Draw effect size line.
797-
axx.hlines(diff, effsize_line_start, xlimhigh,
815+
axx.hlines(diff,
816+
effsize_line_start, xlimhigh,
798817
**reflines_kwargs)
799-
818+
rawdata_axes.set_xlim(-0.5,1.5) # to aligh the axis
800819
# Despine appropriately.
801820
sns.despine(ax=rawdata_axes, bottom=True)
802821
sns.despine(ax=contrast_axes, left=True, right=False)
@@ -823,7 +842,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
823842
custom_contrast_ylim = plot_kwargs['contrast_ylim']
824843
if plot_kwargs['delta2_ylim'] is not None and show_delta2:
825844
custom_delta2_ylim = plot_kwargs['delta2_ylim']
826-
if custom_contrast_ylim!=custom_deltas_ylim:
845+
if custom_contrast_ylim!=custom_delta2_ylim:
827846
err1 = "Please check if `contrast_ylim` and `delta2_ylim` are assigned"
828847
err2 = "with same values."
829848
raise ValueError(err1 + err2)
@@ -869,7 +888,6 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
869888
end_tick = rightend_ticks_raw[k]
870889
ax.hlines(xmin=start_tick, xmax=end_tick,
871890
**redraw_axes_kwargs)
872-
873891
ax.set_ylim(ylim)
874892
del redraw_axes_kwargs['y']
875893

@@ -965,6 +983,8 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
965983

966984
# Because we turned the axes frame off, we also need to draw back
967985
# the y-spine for both axes.
986+
if float_contrast==False:
987+
rawdata_axes.set_xlim(contrast_axes.get_xlim())
968988
og_xlim_raw = rawdata_axes.get_xlim()
969989
rawdata_axes.vlines(og_xlim_raw[0],
970990
og_ylim_raw[0], og_ylim_raw[1],
-699 Bytes
Loading
-1.82 KB
Loading
21.1 KB
Loading
21.5 KB
Loading
25.2 KB
Loading
35.4 KB
Loading
38.7 KB
Loading

0 commit comments

Comments
 (0)