Skip to content

Commit 16529c8

Browse files
committed
Fixes bugs in proportion plot
1 parent cd9dfa9 commit 16529c8

3 files changed

Lines changed: 69 additions & 58 deletions

File tree

dabest/_classes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2831,8 +2831,8 @@ def plot(self, color_col=None,
28312831
if self.__delta2:
28322832
color_col = self.__x2
28332833

2834-
if self.__proportional:
2835-
raw_marker_size = 0.01
2834+
# if self.__proportional:
2835+
# raw_marker_size = 0.01
28362836

28372837
all_kwargs = locals()
28382838
del all_kwargs["self"]

dabest/plotter.py

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,32 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
88

99
"""
1010
Custom function that creates an estimation plot from an EffectSizeDataFrame.
11+
1112
Keywords
1213
--------
1314
EffectSizeDataFrame: A `dabest` EffectSizeDataFrame object.
15+
1416
**plot_kwargs:
1517
color_col=None
18+
1619
raw_marker_size=6, es_marker_size=9,
20+
1721
swarm_label=None, contrast_label=None, delta2_label=None,
1822
swarm_ylim=None, contrast_ylim=None, delta2_ylim=None,
23+
1924
custom_palette=None, swarm_desat=0.5, halfviolin_desat=1,
2025
halfviolin_alpha=0.8,
26+
2127
float_contrast=True,
2228
show_pairs=True,
2329
show_delta2=True,
2430
group_summaries=None,
2531
group_summaries_offset=0.1,
32+
2633
fig_size=None,
2734
dpi=100,
2835
ax=None,
36+
2937
swarmplot_kwargs=None,
3038
violinplot_kwargs=None,
3139
slopegraph_kwargs=None,
@@ -40,7 +48,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
4048
import pandas as pd
4149

4250
from .misc_tools import merge_two_dicts
43-
from .plot_tools import halfviolin, get_swarm_spans, gapped_lines, proportion_error_bar
51+
from .plot_tools import halfviolin, get_swarm_spans, gapped_lines,proportion_error_bar
4452
from ._stats_tools.effsize import _compute_standardizers, _compute_hedges_correction_factor
4553

4654
import logging
@@ -60,15 +68,14 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
6068
ytick_color = plt.rcParams["ytick.color"]
6169
axes_facecolor = plt.rcParams['axes.facecolor']
6270

63-
dabest_obj = EffectSizeDataFrame.dabest_obj
64-
plot_data = EffectSizeDataFrame._plot_data
65-
xvar = EffectSizeDataFrame.xvar
66-
yvar = EffectSizeDataFrame.yvar
67-
is_paired = EffectSizeDataFrame.is_paired
68-
proportional = EffectSizeDataFrame.proportional
69-
delta2 = EffectSizeDataFrame.delta2
70-
mini_meta = EffectSizeDataFrame.mini_meta
71-
effect_size = EffectSizeDataFrame.effect_size
71+
dabest_obj = EffectSizeDataFrame.dabest_obj
72+
plot_data = EffectSizeDataFrame._plot_data
73+
xvar = EffectSizeDataFrame.xvar
74+
yvar = EffectSizeDataFrame.yvar
75+
is_paired = EffectSizeDataFrame.is_paired
76+
delta2 = EffectSizeDataFrame.delta2
77+
mini_meta = EffectSizeDataFrame.mini_meta
78+
effect_size = EffectSizeDataFrame.effect_size
7279

7380
all_plot_groups = dabest_obj._all_plot_groups
7481
idx = dabest_obj.idx
@@ -90,6 +97,8 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
9097
err0 = "`show_delta2` and `show_mini_meta` cannot be True at the same time."
9198
raise ValueError(err0)
9299

100+
101+
93102
# Disable Gardner-Altman plotting if any of the idxs comprise of more than
94103
# two groups or if it is a delta-delta plot.
95104
float_contrast = plot_kwargs["float_contrast"]
@@ -101,15 +110,20 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
101110
float_contrast = False
102111

103112
if show_delta2 or show_mini_meta:
104-
float_contrast = False
113+
float_contrast = False
114+
105115

106-
if not is_paired:
116+
# Disable slopegraph plotting if any of the idxs comprise of more than
117+
# two groups.
118+
if np.all([len(i)==2 for i in idx]) is False:
119+
is_paired = False
120+
# if paired is False, set show_pairs as False.
121+
if is_paired is False:
107122
show_pairs = False
108123
else:
109124
show_pairs = plot_kwargs["show_pairs"]
110125

111126

112-
113127
# Set default kwargs first, then merge with user-dictated ones.
114128
default_swarmplot_kwargs = {'size': plot_kwargs["raw_marker_size"]}
115129
if plot_kwargs["swarmplot_kwargs"] is None:
@@ -137,7 +151,6 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
137151
plot_kwargs["violinplot_kwargs"])
138152

139153

140-
141154
# slopegraph kwargs.
142155
default_slopegraph_kwargs = {'lw':1, 'alpha':0.5}
143156
if plot_kwargs["slopegraph_kwargs"] is None:
@@ -148,6 +161,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
148161

149162

150163

164+
151165
# Zero reference-line kwargs.
152166
default_reflines_kwargs = {'linestyle':'solid', 'linewidth':0.75,
153167
'zorder': 2,
@@ -252,7 +266,6 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
252266
plot_palette_contrast = dict(zip(names, contrast_colors))
253267

254268

255-
256269
# Infer the figsize.
257270
fig_size = plot_kwargs["fig_size"]
258271
if fig_size is None:
@@ -275,6 +288,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
275288
fig_size = (width_inches, height_inches)
276289

277290

291+
278292
# Initialise the figure.
279293
# sns.set(context="talk", style='ticks')
280294
init_fig_kwargs = dict(figsize=fig_size, dpi=plot_kwargs["dpi"],
@@ -333,6 +347,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
333347
gridspec_kw={"width_ratios": width_ratios_ga,
334348
"wspace": 0},
335349
**init_fig_kwargs)
350+
336351
else:
337352
fig, axx = plt.subplots(nrows=2,
338353
gridspec_kw={"hspace": 0.3},
@@ -343,12 +358,13 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
343358
contrast_ax_ylim_low = list()
344359
contrast_ax_ylim_high = list()
345360
contrast_ax_ylim_tickintervals = list()
361+
346362
rawdata_axes = axx[0]
347363
contrast_axes = axx[1]
364+
348365
rawdata_axes.set_frame_on(False)
349366
contrast_axes.set_frame_on(False)
350367

351-
352368
redraw_axes_kwargs = {'colors' : ytick_color,
353369
'facecolors' : ytick_color,
354370
'lw' : 1,
@@ -364,8 +380,20 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
364380
rawdata_axes.set_ylim(bar_ylim)
365381

366382
if show_pairs is True:
367-
# if np.isin(plot_data[yvar], [0, 1]).all() == False:
368-
if proportional == False:
383+
if is_paired == "baseline":
384+
temp_idx = []
385+
for i in idx:
386+
control = i[0]
387+
temp_idx.extend(((control, test) for test in i[1:]))
388+
temp_idx = tuple(temp_idx)
389+
390+
temp_all_plot_groups = []
391+
for i in temp_idx:
392+
temp_all_plot_groups.extend(list(i))
393+
else:
394+
temp_idx = idx
395+
temp_all_plot_groups = all_plot_groups
396+
if np.isin(plot_data[yvar], [0, 1]).all() == False:
369397
# Plot the raw data as a slopegraph.
370398
# Pivot the long (melted) data.
371399
is_proportion = False
@@ -374,20 +402,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
374402
else:
375403
pivot_values = [yvar, color_col]
376404
pivoted_plot_data = pd.pivot(data=plot_data, index=dabest_obj.id_col,
377-
columns=xvar, values=pivot_values)
378-
if is_paired == "baseline":
379-
temp_idx = []
380-
for i in idx:
381-
control = i[0]
382-
temp_idx.extend(((control, test) for test in i[1:]))
383-
temp_idx = tuple(temp_idx)
384-
385-
temp_all_plot_groups = []
386-
for i in temp_idx:
387-
temp_all_plot_groups.extend(list(i))
388-
else:
389-
temp_idx = idx
390-
temp_all_plot_groups = all_plot_groups
405+
columns=xvar, values=pivot_values)
391406

392407
x_start = 0
393408
for ii, current_tuple in enumerate(temp_idx):
@@ -412,13 +427,13 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
412427
slopegraph_kwargs['color'] = ytick_color
413428
else:
414429
color_key = pivoted_plot_data[color_col,
415-
current_tuple[0]].loc[ID]
430+
current_tuple[0]].loc[ID]
416431
if not pd.isna(color_key):
417432
slopegraph_kwargs['color'] = plot_palette_raw[color_key]
418433
slopegraph_kwargs['label'] = color_key
419-
434+
420435
rawdata_axes.plot(x_points, y_points, **slopegraph_kwargs)
421-
x_start = x_start + grp_count
436+
x_start = x_start + grp_count
422437
# Set the tick labels, because the slopegraph plotting doesn't.
423438
rawdata_axes.set_xticks(np.arange(0, len(temp_all_plot_groups)))
424439
rawdata_axes.set_xticklabels(temp_all_plot_groups)
@@ -464,8 +479,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
464479

465480

466481
else:
467-
# if np.isin(plot_data[yvar], [0, 1]).all() == False:
468-
if proportional == False:
482+
if np.isin(plot_data[yvar], [0, 1]).all()==False:
469483
is_proportion = False
470484
# Plot the raw data as a swarmplot.
471485
rawdata_plot = sns.swarmplot(data=plot_data, x=xvar, y=yvar,
@@ -575,11 +589,10 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
575589
ticks_to_skip = np.cumsum([len(t) for t in idx])[:-1].tolist()
576590
ticks_to_skip.insert(0, 0)
577591

578-
# Then obtain the ticks where we have to plot the effect sizes.
579-
ticks_to_plot = [t for t in range(0, len(all_plot_groups))
592+
# Then obtain the ticks where we have to plot the effect sizes.
593+
ticks_to_plot = [t for t in range(0, len(all_plot_groups))
580594
if t not in ticks_to_skip]
581595

582-
583596
# Plot the bootstraps, then the effect sizes and CIs.
584597
es_marker_size = plot_kwargs["es_marker_size"]
585598
halfviolin_alpha = plot_kwargs["halfviolin_alpha"]
@@ -626,7 +639,6 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
626639
contrast_xtick_labels.append("{}\nminus\n{}".format(current_group,
627640
current_control))
628641

629-
630642
# Plot mini-meta violin
631643
if show_mini_meta or show_delta2:
632644
if show_mini_meta:
@@ -859,7 +871,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
859871
custom_contrast_ylim = plot_kwargs['contrast_ylim']
860872
if plot_kwargs['delta2_ylim'] is not None and show_delta2:
861873
custom_delta2_ylim = plot_kwargs['delta2_ylim']
862-
if custom_contrast_ylim!=custom_delta2_ylim:
874+
if custom_contrast_ylim!=custom_deltas_ylim:
863875
err1 = "Please check if `contrast_ylim` and `delta2_ylim` are assigned"
864876
err2 = "with same values."
865877
raise ValueError(err1 + err2)
@@ -929,6 +941,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
929941
else:
930942
# Compute the end of each x-axes line.
931943
rightend_ticks = np.array([len(i)-1 for i in idx]) + np.array(ticks_to_skip)
944+
932945
for ax in [rawdata_axes, contrast_axes]:
933946
sns.despine(ax=ax, bottom=True)
934947

@@ -1037,7 +1050,6 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
10371050
rawdata_axes.xaxis.set_ticks_position('bottom')
10381051
rawdata_axes.yaxis.set_ticks_position('left')
10391052
contrast_axes.xaxis.set_ticks_position('bottom')
1040-
10411053
if float_contrast is False:
10421054
contrast_axes.yaxis.set_ticks_position('left')
10431055

@@ -1050,4 +1062,4 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
10501062

10511063

10521064
# Return the figure.
1053-
return fig
1065+
return fig

dabest/tests/test_10_proportion_plot.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,28 @@
1010

1111
df = create_demo_prop_dataset()
1212

13-
two_groups_unpaired = load(df, idx=("Control 1", "Test 1"))
13+
two_groups_unpaired = load(df, idx=("Control 1", "Test 1"), proportional=True)
1414

1515
two_groups_paired = load(df, idx=("Control 1", "Test 1"),
16-
paired="baseline", id_col="ID")
16+
paired="baseline", id_col="ID",proportional=True)
1717

1818
multi_2group = load(df, idx=(("Control 1", "Test 1",),
19-
("Control 2", "Test 2"))
20-
)
19+
("Control 2", "Test 2")),
20+
proportional=True)
2121

22-
multi_2group_paired = load(df,
23-
idx=(("Control 1", "Test 1"),
22+
multi_2group_paired = load(df, idx=(("Control 1", "Test 1"),
2423
("Control 2", "Test 2")),
25-
paired="baseline", id_col="ID")
24+
paired="baseline", id_col="ID", proportional=True)
2625

2726
shared_control = load(df, idx=("Control 1", "Test 1",
2827
"Test 2", "Test 3",
29-
"Test 4", "Test 5", "Test 6")
30-
)
28+
"Test 4", "Test 5", "Test 6"),
29+
proportional=True)
3130

3231
multi_groups = load(df, idx=(("Control 1", "Test 1",),
3332
("Control 2", "Test 2","Test 3"),
3433
("Control 3", "Test 4","Test 5", "Test 6")
35-
)
34+
),proportional=True
3635
)
3736

3837
@pytest.mark.mpl_image_compare
@@ -77,9 +76,9 @@ def test_108_inset_plots_propdiff():
7776
id_vars=["sex", "index"], var_name="metric")
7877

7978
titanic_dabest1 = load(data=titanic, x="sex", y="survived",
80-
idx=("female","male"))
79+
idx=("female","male"), proportional=True)
8180
titanic_dabest2 = load(data=titanic, x="sex", y="alone",
82-
idx=("female", "male"))
81+
idx=("female", "male"), proportional=True)
8382
# Create Figure.
8483
fig, ax = plt.subplots(nrows=2, ncols=2,
8584
figsize=(15, 15),

0 commit comments

Comments
 (0)