@@ -356,6 +356,9 @@ def __init__(self, data, idx, x, y, paired, id_col, ci,
356356
357357 self .__hedges_g = EffectSizeDataFrame (self , "hedges_g" ,
358358 ** EffectSizeDataFrame_kwargs )
359+
360+ self .__delta_g = EffectSizeDataFrame (self , "delta_g" ,
361+ ** EffectSizeDataFrame_kwargs )
359362
360363 if not paired :
361364 self .__cliffs_delta = EffectSizeDataFrame (self , "cliffs_delta" ,
@@ -488,6 +491,12 @@ def cliffs_delta(self):
488491 """
489492 return self .__cliffs_delta
490493
494+ @property
495+ def delta_g (self ):
496+ """
497+ Returns an :py:class:`EffectSizeDataFrame` for deltas' g, its confidence interval, and relevant statistics, for all comparisons as indicated via the `idx` and `paired` argument in `dabest.load()`.
498+ """
499+ return self .__delta_g
491500
492501 @property
493502 def data (self ):
@@ -668,7 +677,7 @@ def _all_plot_groups(self):
668677 """
669678 return self .__all_plot_groups
670679
671- # %% ../nbs/API/class.ipynb 25
680+ # %% ../nbs/API/class.ipynb 28
672681class DeltaDelta (object ):
673682 """
674683 A class to compute and store the delta-delta statistics for experiments with a 2-by-2 arrangement where two independent variables, A and B, each have two categorical values, 1 and 2. The data is divided into two pairs of two groups, and a primary delta is first calculated as the mean difference between each of the pairs:
@@ -685,10 +694,20 @@ class DeltaDelta(object):
685694
686695
687696 $$\Delta_{\Delta} = \Delta_{2} - \Delta_{1}$$
697+
698+ and a deltas' g value is calculated as the mean difference between the two primary deltas divided by
699+ the standard deviation of the delta-delta value, which is calculated from a pooled variance of the 4 samples:
700+
701+ $$\Delta_{g} = \f rac{\Delta_{\Delta}}{s_{\Delta_{\Delta}}}$$
702+
703+ $$s_{\Delta_{\Delta}} = \sqrt{\f rac{(n_{A_{2}, B_{1}}-1)s_{A_{2}, B_{1}}^2+(n_{A_{1}, B_{1}}-1)s_{A_{1}, B_{1}}^2+(n_{A_{2}, B_{2}}-1)s_{A_{2}, B_{2}}^2+(n_{A_{1}, B_{2}}-1)s_{A_{1}, B_{2}}^2}{(n_{A_{2}, B_{1}} - 1) + (n_{A_{1}, B_{1}} - 1) + (n_{A_{2}, B_{2}} - 1) + (n_{A_{1}, B_{2}} - 1)}}$$
704+
705+ where $s$ is the standard deviation and $n$ is the sample size.
706+
688707
689708 """
690709
691- def __init__ (self , effectsizedataframe , permutation_count ,
710+ def __init__ (self , effectsizedataframe , permutation_count ,bootstraps_delta_delta ,
692711 ci = 95 ):
693712
694713 import numpy as np
@@ -706,22 +725,21 @@ def __init__(self, effectsizedataframe, permutation_count,
706725 self .__dabest_obj = effectsizedataframe .dabest_obj
707726 self .__ci = ci
708727 self .__resamples = effectsizedataframe .resamples
728+ self .__effect_size = effectsizedataframe .effect_size
709729 self .__alpha = ci2g ._compute_alpha_from_ci (ci )
710730 self .__permutation_count = permutation_count
711731 self .__bootstraps = np .array (self .__effsizedf ["bootstraps" ])
712732 self .__control = self .__dabest_obj .experiment_label [0 ]
713733 self .__test = self .__dabest_obj .experiment_label [1 ]
714734
715735
716- # Compute the bootstrap delta-delta and the true dela-delta based on
717- # the raw data
718- self .__bootstraps_delta_delta = self .__bootstraps [1 ] - self .__bootstraps [0 ]
719-
720- self .__difference = self .__effsizedf ["difference" ][1 ] - self .__effsizedf ["difference" ][0 ]
721-
722-
723-
724- sorted_delta_delta = npsort (self .__bootstraps_delta_delta )
736+ # Compute the bootstrap delta-delta or deltas' g and the true dela-delta based on the raw data
737+ if self .__effect_size == "mean_diff" :
738+ self .__bootstraps_delta_delta = bootstraps_delta_delta [2 ]
739+ self .__difference = self .__effsizedf ["difference" ][1 ] - self .__effsizedf ["difference" ][0 ]
740+ else :
741+ self .__bootstraps_delta_delta = bootstraps_delta_delta [0 ]
742+ self .__difference = bootstraps_delta_delta [1 ]
725743
726744 self .__bias_correction = ci2g .compute_meandiff_bias_correction (
727745 self .__bootstraps_delta_delta , self .__difference )
@@ -811,7 +829,10 @@ def __repr__(self, header=True, sigfig=3):
811829 first_line = {"control" : self .__control ,
812830 "test" : self .__test }
813831
814- out1 = "The delta-delta between {control} and {test} " .format (** first_line )
832+ if self .__effect_size == "mean_diff" :
833+ out1 = "The delta-delta between {control} and {test} " .format (** first_line )
834+ else :
835+ out1 = "The deltas' g between {control} and {test} " .format (** first_line )
815836
816837 base_string_fmt = "{:." + str (sigfig ) + "}"
817838 if "." in str (self .__ci ):
@@ -1027,7 +1048,7 @@ def permutations_delta_delta(self):
10271048
10281049
10291050
1030- # %% ../nbs/API/class.ipynb 29
1051+ # %% ../nbs/API/class.ipynb 32
10311052class MiniMetaDelta (object ):
10321053 """
10331054 A class to compute and store the weighted delta.
@@ -1490,7 +1511,7 @@ def permutations_weighted_delta(self):
14901511
14911512
14921513
1493- # %% ../nbs/API/class.ipynb 34
1514+ # %% ../nbs/API/class.ipynb 37
14941515class TwoGroupsEffectSize (object ):
14951516
14961517 """
@@ -1577,7 +1598,8 @@ def __init__(self, control, test, effect_size,
15771598 "cohens_d" : "Cohen's d" ,
15781599 "cohens_h" : "Cohen's h" ,
15791600 "hedges_g" : "Hedges' g" ,
1580- "cliffs_delta" : "Cliff's delta" }
1601+ "cliffs_delta" : "Cliff's delta" ,
1602+ "delta_g" : "deltas' g" }
15811603
15821604
15831605 kosher_es = [a for a in self .__EFFECT_SIZE_DICT .keys ()]
@@ -2177,7 +2199,7 @@ def proportional_difference(self):
21772199 return npnan
21782200
21792201
2180- # %% ../nbs/API/class.ipynb 38
2202+ # %% ../nbs/API/class.ipynb 41
21812203class EffectSizeDataFrame (object ):
21822204 """A class that generates and stores the results of bootstrapped effect
21832205 sizes for several comparisons."""
@@ -2213,6 +2235,7 @@ def __init__(self, dabest, effect_size,
22132235 def __pre_calc (self ):
22142236 import pandas as pd
22152237 from .misc_tools import print_greeting , get_varname
2238+ from ._stats_tools import confint_2group_diff as ci2g
22162239
22172240 idx = self .__dabest_obj .idx
22182241 dat = self .__dabest_obj ._plot_data
@@ -2221,6 +2244,24 @@ def __pre_calc(self):
22212244
22222245 out = []
22232246 reprs = []
2247+
2248+ if self .__delta2 == True :
2249+ mixed_data = []
2250+ for j , current_tuple in enumerate (idx ):
2251+ if self .__is_paired != "sequential" :
2252+ cname = current_tuple [0 ]
2253+ control = dat [dat [xvar ] == cname ][yvar ].copy ()
2254+
2255+ for ix , tname in enumerate (current_tuple [1 :]):
2256+ if self .__is_paired == "sequential" :
2257+ cname = current_tuple [ix ]
2258+ control = dat [dat [xvar ] == cname ][yvar ].copy ()
2259+ test = dat [dat [xvar ] == tname ][yvar ].copy ()
2260+ mixed_data .append (control )
2261+ mixed_data .append (test )
2262+ bootstraps_delta_delta = ci2g .compute_delta2_bootstrapped_diff (mixed_data [0 ], mixed_data [1 ], mixed_data [2 ], mixed_data [3 ],
2263+ self .__is_paired , self .__resamples , self .__random_seed )
2264+
22242265
22252266 for j , current_tuple in enumerate (idx ):
22262267 if self .__is_paired != "sequential" :
@@ -2248,7 +2289,7 @@ def __pre_calc(self):
22482289 r_dict ["test_N" ] = int (len (test ))
22492290 out .append (r_dict )
22502291 if j == len (idx )- 1 and ix == len (current_tuple )- 2 :
2251- if self .__delta2 and self .__effect_size == "mean_diff" :
2292+ if self .__delta2 and self .__effect_size in [ "mean_diff" , "delta_g" ] :
22522293 resamp_count = False
22532294 def_pval = False
22542295 elif self .__mini_meta and self .__effect_size == "mean_diff" :
@@ -2318,12 +2359,13 @@ def __pre_calc(self):
23182359 self .__results .insert (5 , 'is_paired' , self .__results .apply (lambda _ : None , axis = 1 ))
23192360
23202361 # Create and compute the delta-delta statistics
2321- if self .__delta2 is True and self . __effect_size == "mean_diff" :
2362+ if self .__delta2 is True :
23222363 self .__delta_delta = DeltaDelta (self ,
23232364 self .__permutation_count ,
2365+ bootstraps_delta_delta ,
23242366 self .__ci )
23252367 reprs .append (self .__delta_delta .__repr__ (header = False ))
2326- elif self .__delta2 is True and self .__effect_size != "mean_diff" :
2368+ elif self .__delta2 is True and self .__effect_size not in [ "mean_diff" , "delta_g" ] :
23272369 self .__delta_delta = "Delta-delta is not supported for {}." .format (self .__effect_size )
23282370 else :
23292371 self .__delta_delta = "`delta2` is False; delta-delta is therefore not calculated."
@@ -2423,8 +2465,8 @@ def plot(self, color_col=None,
24232465
24242466 raw_marker_size = 6 , es_marker_size = 9 ,
24252467
2426- swarm_label = None , barchart_label = None , contrast_label = None , delta2_label = None ,
2427- swarm_ylim = None , barchart_ylim = None , contrast_ylim = None , delta2_ylim = None ,
2468+ swarm_label = None , contrast_label = None , delta2_label = None ,
2469+ swarm_ylim = None , contrast_ylim = None , delta2_ylim = None ,
24282470
24292471 custom_palette = None , swarm_desat = 0.5 , halfviolin_desat = 1 ,
24302472 halfviolin_alpha = 0.8 ,
@@ -2453,7 +2495,10 @@ def plot(self, color_col=None,
24532495 sankey_kwargs = None ,
24542496 reflines_kwargs = None ,
24552497 group_summary_kwargs = None ,
2456- legend_kwargs = None ):
2498+ legend_kwargs = None ,
2499+ title = None , fontsize_title = 16 ,
2500+ fontsize_rawxlabel = 12 ,fontsize_rawylabel = 12 ,fontsize_contrastxlabel = 12 , fontsize_contrastylabel = 12 ,
2501+ fontsize_delta2label = 12 ):
24572502
24582503 """
24592504 Creates an estimation plot for the effect size of interest.
@@ -2574,6 +2619,24 @@ def plot(self, color_col=None,
25742619 `legend` command here, as a dict. If None, the following keywords
25752620 are passed to matplotlib.Axes.legend : {'loc':'upper left',
25762621 'frameon':False}.
2622+ title : string, default None
2623+ Title for the plot. If None, no title will be displayed. Pass any
2624+ keyword arguments accepted by the matplotlib.pyplot.suptitle `t` command here,
2625+ as a string.
2626+ fontsize_title : float or {'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'}, default 'large'
2627+ Font size for the plot title. If a float, the fontsize in points. The
2628+ string values denote sizes relative to the default font size. Pass any keyword arguments accepted
2629+ by the matplotlib.pyplot.suptitle `fontsize` command here, as a string.
2630+ fontsize_rawxlabel : float, default 12
2631+ Font size for the raw axes xlabel.
2632+ fontsize_rawylabel : float, default 12
2633+ Font size for the raw axes ylabel.
2634+ fontsize_contrastxlabel : float, default 12
2635+ Font size for the contrast axes xlabel.
2636+ fontsize_contrastylabel : float, default 12
2637+ Font size for the contrast axes ylabel.
2638+ fontsize_delta2label : float, default 12
2639+ Font size for the delta-delta axes ylabel.
25772640
25782641
25792642 Returns
@@ -2778,7 +2841,7 @@ def delta_delta(self):
27782841
27792842
27802843
2781- # %% ../nbs/API/class.ipynb 56
2844+ # %% ../nbs/API/class.ipynb 59
27822845class PermutationTest :
27832846 """
27842847 A class to compute and report permutation tests.
@@ -2790,7 +2853,7 @@ class PermutationTest:
27902853 These should be numerical iterables.
27912854 effect_size : string.
27922855 Any one of the following are accepted inputs:
2793- 'mean_diff', 'median_diff', 'cohens_d', 'hedges_g', or 'cliffs_delta'
2856+ 'mean_diff', 'median_diff', 'cohens_d', 'hedges_g', 'delta_g" or 'cliffs_delta'
27942857 is_paired : string, default None
27952858 permutation_count : int, default 10000
27962859 The number of permutations (reshuffles) to perform.
0 commit comments