Skip to content

Commit f01024c

Browse files
committed
Add es_paired_lines and es_paired_lines_kwargs, and added tutorial and tests for this feature.
1 parent 28b23e5 commit f01024c

File tree

129 files changed

+912
-652
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+912
-652
lines changed

dabest/_effsize_objects.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,10 @@ def plot(
10391039
es_errorbar_kwargs=None,
10401040

10411041
prop_sample_counts=False,
1042-
prop_sample_counts_kwargs=None
1042+
prop_sample_counts_kwargs=None,
1043+
1044+
es_paired_lines=True,
1045+
es_paired_lines_kwargs=None,
10431046
):
10441047
"""
10451048
Creates an estimation plot for the effect size of interest.
@@ -1193,17 +1196,17 @@ def plot(
11931196
contrast_bars_kwargs : dict, default None
11941197
Pass relevant keyword arguments to the contrast bars. Pass any keyword arguments accepted by
11951198
matplotlib.patches.Rectangle here, as a string. If None, the following keywords are passed:
1196-
{"color": None, "alpha": 0.3}
1199+
{"color": None, "alpha": 0.3, "zorder":-3}
11971200
swarm_bars_kwargs : dict, default None
11981201
Pass relevant keyword arguments to the swarm bars. Pass any keyword arguments accepted by
11991202
matplotlib.patches.Rectangle here, as a string. If None, the following keywords are passed:
1200-
{"color": None, "alpha": 0.3}
1203+
{"color": None, "alpha": 0.3, "zorder":-3}
12011204
12021205
summary_bars : list, default None
12031206
Pass a list of indices of the contrast objects to have summary bars displayed on the plot.
12041207
For example, [0,1] will show summary bars for the first two contrast objects.
12051208
summary_bars_kwargs: dict, default None
1206-
If None, the following keywords are passed: {"span_ax": False, "color": None, "alpha": 0.15}
1209+
If None, the following keywords are passed: {"span_ax": False, "color": None, "alpha": 0.15, "zorder":-3}
12071210
delta_text : boolean, default True
12081211
Whether or not to display the text deltas.
12091212
delta_text_kwargs : dict, default None
@@ -1251,7 +1254,13 @@ def plot(
12511254
Show the sample counts for each group in proportional plots
12521255
prop_sample_counts_kwargs: dict, default None
12531256
Pass relevant keyword arguments. If None, the following keywords are passed:
1254-
{'color': 'k', 'zorder': 5, 'ha': 'center', 'va': 'center'}
1257+
{'color': 'k', 'zorder': 5, 'ha': 'center', 'va': 'center'},
1258+
1259+
es_paired_lines: bool, default True
1260+
Whether or not to add lines to connect the effect size curves in paired plots.
1261+
es_paired_lines_kwargs: dict, default None
1262+
Pass relevant plot keyword arguments. If None, the following keywords are passed:
1263+
{"linestyle": "-", "linewidth": 2, "zorder": -2, "color": 'dimgray', "alpha": 1}
12551264
12561265
12571266
Returns

dabest/misc_tools.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@ def get_unique_categories(names):
9393
# For dict_keys and other iterables
9494
return np.unique(list(names))
9595

96-
def get_params(effectsize_df, plot_kwargs):
96+
def get_params(effectsize_df: object, plot_kwargs: dict):
9797
"""
98-
Extracts the parameters from the `effectsize_df` and `plot_kwargs` objects for use in the plotter function.
98+
Extracts parameters from the `effectsize_df` and `plot_kwargs` objects for use in the plotter function.
9999
100100
Parameters
101101
----------
102-
effectsize_df : object (Dataframe)
102+
effectsize_df : object
103103
A `dabest` EffectSizeDataFrame object.
104104
plot_kwargs : dict
105105
Kwargs passed to the plot function.
@@ -119,7 +119,6 @@ def get_params(effectsize_df, plot_kwargs):
119119
x1_level = dabest_obj.x1_level
120120
experiment_label = dabest_obj.experiment_label
121121

122-
123122
if effect_size not in ["mean_diff", "delta_g"] or not delta2:
124123
show_delta2 = False
125124
else:
@@ -352,7 +351,8 @@ def get_kwargs(plot_kwargs, ytick_color):
352351
default_summary_bars_kwargs = {
353352
"span_ax": False,
354353
"color": None,
355-
"alpha": 0.15
354+
"alpha": 0.15,
355+
"zorder":-3
356356
}
357357
if plot_kwargs["summary_bars_kwargs"] is None:
358358
summary_bars_kwargs = default_summary_bars_kwargs
@@ -362,7 +362,8 @@ def get_kwargs(plot_kwargs, ytick_color):
362362
# Swarm bars kwargs.
363363
default_swarm_bars_kwargs = {
364364
"color": None,
365-
"alpha": 0.3
365+
"alpha": 0.3,
366+
"zorder":-3
366367
}
367368
if plot_kwargs["swarm_bars_kwargs"] is None:
368369
swarm_bars_kwargs = default_swarm_bars_kwargs
@@ -372,7 +373,8 @@ def get_kwargs(plot_kwargs, ytick_color):
372373
# Contrast bars kwargs.
373374
default_contrast_bars_kwargs = {
374375
"color": None,
375-
"alpha": 0.3
376+
"alpha": 0.3,
377+
"zorder":-3
376378
}
377379
if plot_kwargs["contrast_bars_kwargs"] is None:
378380
contrast_bars_kwargs = default_contrast_bars_kwargs
@@ -447,11 +449,25 @@ def get_kwargs(plot_kwargs, ytick_color):
447449
else:
448450
prop_sample_counts_kwargs = merge_two_dicts(default_prop_sample_counts_kwargs, plot_kwargs['prop_sample_counts_kwargs'])
449451

452+
453+
# RM Lines kwargs
454+
default_es_paired_lines_kwargs = {
455+
"linestyle": "-",
456+
"linewidth": 2,
457+
"zorder": -2,
458+
"color": 'dimgray',
459+
"alpha": 1
460+
}
461+
if plot_kwargs["es_paired_lines_kwargs"] is None:
462+
es_paired_lines_kwargs = default_es_paired_lines_kwargs
463+
else:
464+
es_paired_lines_kwargs = merge_two_dicts(default_es_paired_lines_kwargs, plot_kwargs["es_paired_lines_kwargs"])
465+
450466
# Return the kwargs.
451467
return (swarmplot_kwargs, barplot_kwargs, sankey_kwargs, violinplot_kwargs, slopegraph_kwargs,
452468
reflines_kwargs, legend_kwargs, group_summaries_kwargs, redraw_axes_kwargs, delta_dot_kwargs,
453469
delta_text_kwargs, summary_bars_kwargs, swarm_bars_kwargs, contrast_bars_kwargs, table_kwargs, gridkey_kwargs,
454-
es_marker_kwargs, es_errorbar_kwargs, prop_sample_counts_kwargs)
470+
es_marker_kwargs, es_errorbar_kwargs, prop_sample_counts_kwargs, es_paired_lines_kwargs)
455471

456472

457473
def get_color_palette(plot_kwargs, plot_data, xvar, show_pairs, idx, all_plot_groups):
@@ -485,6 +501,7 @@ def get_color_palette(plot_kwargs, plot_data, xvar, show_pairs, idx, all_plot_gr
485501
bootstraps_color_by_group = False
486502
if show_pairs:
487503
bootstraps_color_by_group = False
504+
488505
# Handle the color palette.
489506
filled = True
490507
empty_circle = plot_kwargs["empty_circle"]

dabest/plot_tools.py

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -949,14 +949,14 @@ def summary_bars_plotter(summary_bars: list, results: object, ax_to_plot: object
949949
ax_to_plot.add_patch(mpatches.Rectangle(
950950
(summary_ci_low, starting_location),
951951
summary_ci_high-summary_ci_low, summary_ymin+1,
952-
zorder=-2, color=summary_color,
952+
color=summary_color,
953953
**summary_bars_kwargs)
954954
)
955955
else:
956956
ax_to_plot.add_patch(mpatches.Rectangle(
957957
(starting_location, summary_ci_low),
958958
summary_xmax+1, summary_ci_high-summary_ci_low,
959-
zorder=-2, color=summary_color,
959+
color=summary_color,
960960
**summary_bars_kwargs)
961961
)
962962

@@ -1023,13 +1023,11 @@ def contrast_bars_plotter(results: object, ax_to_plot: object, swarm_plot_ax: o
10231023
if type(contrast_bars_colors) == list
10241024
else unpacked_idx[int(contrast_bars_x)]
10251025
)
1026-
ax_to_plot.add_patch(mpatches.Rectangle((0,contrast_bars_x-0.5),contrast_bars_y, 0.5, zorder=-10, color=contrast_bars_colors[idx_selector], **contrast_bars_kwargs))
1026+
ax_to_plot.add_patch(mpatches.Rectangle((0,contrast_bars_x-0.5),contrast_bars_y, 0.5, color=contrast_bars_colors[idx_selector], **contrast_bars_kwargs))
10271027

1028-
if show_mini_meta:
1029-
ax_to_plot.add_patch(mpatches.Rectangle((0, max(swarm_plot_ax.get_yticks())-0.5), mini_meta_delta.difference, 0.5, zorder=-10, color='black', **contrast_bars_kwargs))
1030-
1031-
if show_delta2:
1032-
ax_to_plot.add_patch(mpatches.Rectangle((0, max(swarm_plot_ax.get_yticks())-0.5), delta_delta.difference, 0.5, zorder=-10, color='black', **contrast_bars_kwargs))
1028+
if show_mini_meta or show_delta2:
1029+
diff = mini_meta_delta.difference if show_mini_meta else delta_delta.difference
1030+
ax_to_plot.add_patch(mpatches.Rectangle((0, max(swarm_plot_ax.get_yticks())-0.5), diff, 0.5, color='black', **contrast_bars_kwargs))
10331031

10341032
else:
10351033
for contrast_bars_x,contrast_bars_y in zip(ticks_to_plot, contrast_means):
@@ -1038,13 +1036,11 @@ def contrast_bars_plotter(results: object, ax_to_plot: object, swarm_plot_ax: o
10381036
if type(contrast_bars_colors) == list
10391037
else unpacked_idx[int(contrast_bars_x)]
10401038
)
1041-
ax_to_plot.add_patch(mpatches.Rectangle((contrast_bars_x-0.25,0),0.5, contrast_bars_y, zorder=-1, color=contrast_bars_colors[idx_selector], **contrast_bars_kwargs))
1039+
ax_to_plot.add_patch(mpatches.Rectangle((contrast_bars_x-0.25,0),0.5, contrast_bars_y, color=contrast_bars_colors[idx_selector], **contrast_bars_kwargs))
10421040

1043-
if show_mini_meta:
1044-
ax_to_plot.add_patch(mpatches.Rectangle((max(swarm_plot_ax.get_xticks())+2-0.25,0),0.5, mini_meta_delta.difference, zorder=-1, color='black', **contrast_bars_kwargs))
1045-
1046-
if show_delta2:
1047-
ax_to_plot.add_patch(mpatches.Rectangle((max(swarm_plot_ax.get_xticks())+2-0.25,0),0.5, delta_delta.difference, zorder=-1, color='black', **contrast_bars_kwargs))
1041+
if show_mini_meta or show_delta2:
1042+
diff = mini_meta_delta.difference if show_mini_meta else delta_delta.difference
1043+
ax_to_plot.add_patch(mpatches.Rectangle((max(swarm_plot_ax.get_xticks())+2-0.25,0),0.5, diff, color='black', **contrast_bars_kwargs))
10481044

10491045
ax_to_plot.set_xlim(og_xlim)
10501046
ax_to_plot.set_ylim(og_ylim)
@@ -1103,7 +1099,7 @@ def swarm_bars_plotter(plot_data: object, xvar: str, yvar: str, ax: object,
11031099
else unpacked_idx[swarm_bars_x]
11041100
)
11051101
ax.add_patch(mpatches.Rectangle((swarm_bars_x-0.25,0), 0.5, swarm_bars_y,
1106-
zorder=-1,color=swarm_bars_colors[idx_selector],**swarm_bars_kwargs))
1102+
color=swarm_bars_colors[idx_selector],**swarm_bars_kwargs))
11071103

11081104
ax.set_xlim(og_xlim)
11091105
ax.set_ylim(og_ylim)
@@ -1344,15 +1340,12 @@ def slopegraph_plotter(dabest_obj, plot_data, xvar, yvar, color_col, plot_palett
13441340
"""
13451341
# Jitter Kwargs
13461342
# With help from devMJBL
1347-
jitter = slopegraph_kwargs["jitter"]
1343+
jitter = slopegraph_kwargs.pop("jitter")
13481344
if jitter >= 1:
13491345
err0 = "Jitter value is too high. Defaulting to 1."
13501346
warnings.warn(err0)
13511347
jitter = 1
1352-
rng = np.random.default_rng(slopegraph_kwargs["jitter_seed"])
1353-
for key in ["jitter", "jitter_seed"]:
1354-
if key in slopegraph_kwargs:
1355-
slopegraph_kwargs.pop(key)
1348+
rng = np.random.default_rng(slopegraph_kwargs.pop("jitter_seed"))
13561349

13571350
# Pivot the long (melted) data.
13581351
if color_col is None:
@@ -1539,7 +1532,8 @@ def plot_minimeta_or_deltadelta_violins(show_mini_meta, effectsize_df, ci_type,
15391532

15401533
def effect_size_curve_plotter(ticks_to_plot, results, ci_type, contrast_axes, violinplot_kwargs, halfviolin_alpha,
15411534
ytick_color, bootstraps_color_by_group, plot_palette_contrast,
1542-
horizontal, es_marker_kwargs, es_errorbar_kwargs):
1535+
horizontal, es_marker_kwargs, es_errorbar_kwargs,
1536+
idx, is_paired, es_paired_lines, es_paired_lines_kwargs):
15431537
"""
15441538
Add effect size curves to the contrast plot.
15451539
@@ -1571,6 +1565,14 @@ def effect_size_curve_plotter(ticks_to_plot, results, ci_type, contrast_axes, vi
15711565
Keyword arguments for the effectsize marker.
15721566
es_errorbar_kwargs: dict
15731567
Keyword arguments for the effectsize errorbar.
1568+
idx : list
1569+
List of indices of the raw groups.
1570+
is_paired : bool
1571+
Whether the data is paired.
1572+
es_paired_lines : bool
1573+
Whether to add lines for repeated measures data.
1574+
es_paired_lines_kwargs : dict
1575+
Keyword arguments for the repeated measures lines.
15741576
"""
15751577

15761578
# Plot the curves
@@ -1618,21 +1620,56 @@ def effect_size_curve_plotter(ticks_to_plot, results, ci_type, contrast_axes, vi
16181620
contrast_axes.plot(
16191621
effsize_x,
16201622
effsize_y,
1621-
# color=ytick_color,
16221623
**es_marker_kwargs
16231624
)
16241625

16251626
# Plot the confidence interval.
16261627
contrast_axes.plot(
16271628
ci_x,
16281629
ci_y,
1629-
# color=ytick_color,
16301630
**es_errorbar_kwargs
16311631
)
16321632

16331633
contrast_xtick_labels.append(
16341634
"{}\nminus\n{}".format(current_group, current_control)
16351635
)
1636+
1637+
# Add lines for repeated measures data
1638+
if is_paired and es_paired_lines:
1639+
temp_num = 0
1640+
lines_to_plot_list = []
1641+
1642+
for group in idx:
1643+
new_group = []
1644+
if len(group) >= 2:
1645+
new_group.append(temp_num)
1646+
for i in range(1, len(group)):
1647+
new_group.append(temp_num+i)
1648+
temp_num += len(group)
1649+
lines_to_plot_list.append(new_group)
1650+
1651+
for group in lines_to_plot_list:
1652+
if len(group) > 0:
1653+
mean_diffs_for_lines = []
1654+
for ticks in group:
1655+
if ticks in ticks_to_plot:
1656+
mean_diffs_for_lines.append(results.loc[ticks_to_plot.index(ticks)]["difference"])
1657+
else:
1658+
mean_diffs_for_lines.append(int(0))
1659+
1660+
if horizontal:
1661+
contrast_axes.plot(
1662+
mean_diffs_for_lines,
1663+
group,
1664+
**es_paired_lines_kwargs
1665+
)
1666+
else:
1667+
contrast_axes.plot(
1668+
group,
1669+
mean_diffs_for_lines,
1670+
**es_paired_lines_kwargs
1671+
)
1672+
16361673
return current_group, current_control, current_effsize, contrast_xtick_labels
16371674

16381675
def gridkey_plotter(is_paired, idx, all_plot_groups, gridkey_rows, rawdata_axes, contrast_axes,

0 commit comments

Comments
 (0)