Skip to content

Commit 2d1713e

Browse files
committed
Add extra delta-delta violin to 2x2 plot
- Add extra delta-delta violin to 2x2 plot
1 parent 023aa70 commit 2d1713e

4 files changed

Lines changed: 209 additions & 62 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,4 @@ real.py
127127
0to2_beforeduringafter.csv
128128
test.ipynb
129129
TrhCsCh.csv
130+
*.py

dabest/_api.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66

77
def load(data, idx=None, x=None, y=None, paired=None, id_col=None,
8-
ci=95, resamples=5000, random_seed=12345, proportional=False, var2 = False, status = None):
8+
ci=95, resamples=5000, random_seed=12345, proportional=False,
9+
delta2 = False, experiment = None):
910
'''
1011
Loads data in preparation for estimation statistics.
1112
@@ -18,7 +19,10 @@ def load(data, idx=None, x=None, y=None, paired=None, id_col=None,
1819
List of column names (if 'x' is not supplied) or of category names
1920
(if 'x' is supplied). This can be expressed as a tuple of tuples,
2021
with each individual tuple producing its own contrast plot
21-
x : string, default None
22+
x : string or list, default None
23+
Column name(s) of the independent variable. This can be expressed as
24+
a list of 2 elements if and only if 'delta2' is True; otherwise it
25+
can only be a string.
2226
y : string, default None
2327
Column names for data to be plotted on the x-axis and y-axis.
2428
paired : string, default None
@@ -37,6 +41,19 @@ def load(data, idx=None, x=None, y=None, paired=None, id_col=None,
3741
reported are replicable.
3842
proportional : boolean, default False.
3943
TO INCLUDE MORE DESCRIPTION ABOUT DATA FORMAT
44+
delta2 : boolean, default False
45+
Indicator of delta-delta experiment
46+
experiment : String, default None
47+
The name of the column of the dataframe which contains the label of
48+
experiments
49+
experiment_lab : list, default None
50+
A list of String to specify the order of subplots for delta-delta plots.
51+
This can be expressed as a list of 2 elements if and only if 'delta2'
52+
is True; otherwise it can only be a string.
53+
x1_level : list, default None
54+
A list of String to specify the order of subplots for delta-delta plots.
55+
This can be expressed as a list of 2 elements if and only if 'delta2'
56+
is True; otherwise it can only be a string.
4057
4158
Returns
4259
-------
@@ -65,4 +82,4 @@ def load(data, idx=None, x=None, y=None, paired=None, id_col=None,
6582
'''
6683
from ._classes import Dabest
6784

68-
return Dabest(data, idx, x, y, paired, id_col, ci, resamples, random_seed, proportional, var2, status)
85+
return Dabest(data, idx, x, y, paired, id_col, ci, resamples, random_seed, proportional, delta2, experiment)

dabest/_classes.py

Lines changed: 101 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Dabest(object):
1010
"""
1111

1212
def __init__(self, data, idx, x, y, paired, id_col, ci, resamples,
13-
random_seed, proportional, var2, status):
13+
random_seed, proportional, delta2, experiment):
1414

1515
"""
1616
Parses and stores pandas DataFrames in preparation for estimation
@@ -23,8 +23,8 @@ def __init__(self, data, idx, x, y, paired, id_col, ci, resamples,
2323
import pandas as pd
2424
import seaborn as sns
2525

26-
self.__var2 = var2
27-
self.__status = status
26+
self.__delta2 = delta2
27+
self.__experiment = experiment
2828
self.__ci = ci
2929
self.__data = data
3030
self.__id_col = id_col
@@ -41,38 +41,38 @@ def __init__(self, data, idx, x, y, paired, id_col, ci, resamples,
4141

4242

4343
# check if this is a 2x2 ANOVA case and x & y are valid columns:
44-
if var2:
44+
if delta2:
4545
if len(x) != 2:
46-
err0 = '`var2` is True but the number of variables indicated by `x` is {}.'.format(len(x))
46+
err0 = '`delta2` is True but the number of variables indicated by `x` is {}.'.format(len(x))
4747
raise ValueError(err0)
4848
if any(i not in data_in.columns for i in x):
4949
err = 'Not all of {0} is a column in `data`. Please check.'.format(x)
5050
raise IndexError(err)
5151
if y not in data_in.columns:
5252
err = '{0} is not a column in `data`. Please check.'.format(y)
5353
raise IndexError(err)
54-
if status not in data_in.columns:
55-
err = '{0} is not a column in `data`. Please check.'.format(status)
54+
if experiment not in data_in.columns:
55+
err = '{0} is not a column in `data`. Please check.'.format(experiment)
5656
raise IndexError(err)
5757

5858

5959

6060
# check if idx is specified
61-
if not var2 and not idx:
61+
if not delta2 and not idx:
6262
err = '`idx` is not a column in `data`. Please check.'
6363
raise IndexError(err)
6464

6565

6666
# create new x & idx and record the second variable if this is a valid 2x2 ANOVA case
67-
if var2:
68-
# add a new column which is a combination of experiment status and the first variable
69-
new_col_name = status+x[0]
67+
if delta2:
68+
# add a new column which is a combination of experiment and the first variable
69+
new_col_name = experiment+x[0]
7070
while new_col_name in data_in.columns:
7171
new_col_name += "_"
72-
data_in[new_col_name] = data_in[x[0]].apply(lambda x: str(x)) + " " + data_in[status].apply(lambda x: str(x))
72+
data_in[new_col_name] = data_in[x[0]].apply(lambda x: str(x)) + " " + data_in[experiment].apply(lambda x: str(x))
7373

7474
#create idx
75-
experiment = data_in[status].unique()
75+
experiment = data_in[experiment].unique()
7676
x1_level = data_in[x[0]].unique()
7777
idx = []
7878
for i in experiment:
@@ -91,7 +91,7 @@ def __init__(self, data, idx, x, y, paired, id_col, ci, resamples,
9191
self.__second = None
9292
self.__idx = idx
9393
self.__first = None
94-
self.__experiment = experiment
94+
self.__experiment = None
9595

9696
# Determine the kind of estimation plot we need to produce.
9797
if all([isinstance(i, str) for i in idx]):
@@ -254,7 +254,11 @@ def __init__(self, data, idx, x, y, paired, id_col, ci, resamples,
254254
EffectSizeDataFrame_kwargs = dict(ci=ci, is_paired=paired,
255255
random_seed=random_seed,
256256
resamples=resamples,
257-
proportional=proportional, var2=var2, second=self.__second)
257+
proportional=proportional,
258+
delta2=delta2,
259+
experiment = self.__experiment,
260+
first = self.__first,
261+
second=self.__second)
258262

259263
self.__mean_diff = EffectSizeDataFrame(self, "mean_diff",
260264
**EffectSizeDataFrame_kwargs)
@@ -323,6 +327,9 @@ def __repr__(self):
323327
for ix, test_name in enumerate(current_tuple[1:]):
324328
comparisons.append("{} minus {}".format(test_name, control_name))
325329

330+
if self.__delta2:
331+
comparison.append("{} minus {}".format(self.__experiment[1], self.__experiment[0]))
332+
326333
for j, g in enumerate(comparisons):
327334
out.append("{}. {}".format(j+1, g))
328335

@@ -565,16 +572,26 @@ def idx(self):
565572
return self.__idx
566573

567574

575+
@property
576+
def first(self):
577+
return self.__first
578+
579+
568580
@property
569581
def second(self):
570582
return self.__second
571583

572584

573585
@property
574-
def var2(self):
575-
return self.__var2
586+
def experiment(self):
587+
return self.__experiment
576588

577589

590+
@property
591+
def delta2(self):
592+
return self.__delta2
593+
594+
578595
@property
579596
def is_paired(self):
580597
"""
@@ -687,7 +704,8 @@ def __init__(self, control, test, effect_size,
687704
is_paired=None, ci=95,
688705
resamples=5000,
689706
permutation_count=5000,
690-
random_seed=12345):
707+
random_seed=12345,
708+
first=None, delta2=False):
691709

692710
"""
693711
Compute the effect size between two groups.
@@ -851,20 +869,24 @@ def __init__(self, control, test, effect_size,
851869
self.__random_seed = random_seed
852870
self.__ci = ci
853871
self.__alpha = ci2g._compute_alpha_from_ci(ci)
854-
872+
self.__delta2 = delta2
873+
self.__first = first
855874

856875
self.__difference = es.two_group_difference(
857876
control, test, is_paired, effect_size)
858-
877+
859878
self.__jackknives = ci2g.compute_meandiff_jackknife(
860879
control, test, is_paired, effect_size)
861880

862881
self.__acceleration_value = ci2g._calc_accel(self.__jackknives)
863882

864-
bootstraps = ci2g.compute_bootstrapped_diff(
883+
if not delta2:
884+
bootstraps = ci2g.compute_bootstrapped_diff(
865885
control, test, is_paired, effect_size,
866886
resamples, random_seed)
867-
self.__bootstraps = npsort(bootstraps)
887+
self.__bootstraps = npsort(bootstraps)
888+
else:
889+
self.__bootstraps = npsort(self.__test-self.__control)
868890

869891
# Added in v0.2.6.
870892
# Raises a UserWarning if there are any infiinities in the bootstraps.
@@ -924,14 +946,19 @@ def __init__(self, control, test, effect_size,
924946
self.__bca_high = self.__difference
925947
warnings.warn(err_temp.substitute(lim_type="upper"),
926948
stacklevel=0)
949+
if not self.__delta2:
950+
# Compute percentile intervals.
951+
pct_idx_low = int((self.__alpha/2) * resamples)
952+
pct_idx_high = int((1-(self.__alpha/2)) * resamples)
927953

928-
# Compute percentile intervals.
929-
pct_idx_low = int((self.__alpha/2) * resamples)
930-
pct_idx_high = int((1-(self.__alpha/2)) * resamples)
931-
932-
self.__pct_interval_idx = (pct_idx_low, pct_idx_high)
933-
self.__pct_low = self.__bootstraps[pct_idx_low]
934-
self.__pct_high = self.__bootstraps[pct_idx_high]
954+
self.__pct_interval_idx = (pct_idx_low, pct_idx_high)
955+
self.__pct_low = self.__bootstraps[pct_idx_low]
956+
self.__pct_high = self.__bootstraps[pct_idx_high]
957+
958+
else:
959+
self.__pct_interval_idx = None
960+
self.__pct_low = None
961+
self.__pct_high = None
935962

936963
# Perform statistical tests.
937964

@@ -1067,7 +1094,10 @@ def __repr__(self, show_resample_count=True, define_pval=True, sigfig=3):
10671094
"es" : self.__EFFECT_SIZE_DICT[self.__effect_size],
10681095
"paired_status": PAIRED_STATUS[str(self.__is_paired)]}
10691096

1070-
out1 = "The {paired_status} {es} {rm_status}".format(**first_line)
1097+
if self.__delta2:
1098+
out1 = "The delta-delta {es}"
1099+
else:
1100+
out1 = "The {paired_status} {es} {rm_status}".format(**first_line)
10711101

10721102
base_string_fmt = "{:." + str(sigfig) + "}"
10731103
if "." in str(self.__ci):
@@ -1454,7 +1484,9 @@ def __init__(self, dabest, effect_size,
14541484
is_paired, ci=95, proportional=False,
14551485
resamples=5000,
14561486
permutation_count=5000,
1457-
random_seed=12345, second=None, var2=False):
1487+
random_seed=12345,
1488+
first=None, second=None,
1489+
delta2=False, experiment=None):
14581490
"""
14591491
Parses the data from a Dabest object, enabling plotting and printing
14601492
capability for the effect size of interest.
@@ -1468,8 +1500,10 @@ def __init__(self, dabest, effect_size,
14681500
self.__permutation_count = permutation_count
14691501
self.__random_seed = random_seed
14701502
self.__proportional = proportional
1503+
self.__first = first
1504+
self.__experiment = experiment
14711505
self.__second = second
1472-
self.__var2 = var2
1506+
self.__delta2 = delta2
14731507

14741508

14751509
def __pre_calc(self):
@@ -1524,6 +1558,28 @@ def __pre_calc(self):
15241558

15251559
reprs.append(text_repr)
15261560

1561+
if self.__delta2:
1562+
delta = TwoGroupsEffectSize(out[0]["bootstraps"],
1563+
out[1]["bootstraps"],
1564+
self.__effect_size,
1565+
True,
1566+
self.__ci,
1567+
self.__resamples,
1568+
self.__permutation_count,
1569+
self.__random_seed,
1570+
self.__first,
1571+
self.__delta2
1572+
)
1573+
r_dict = delta.to_dict()
1574+
r_dict["control"] = self.__experiment[1]
1575+
r_dict["test"] = self.__experiment[0]
1576+
r_dict["control_N"] = self.__resamples
1577+
r_dict["test_N"] = self.__resamples
1578+
out.append(r_dict)
1579+
to_replace = "between {} and {} is".format(self.__experiment[0], self.__experiment[1])
1580+
text_repr = text_repr.replace("is", to_replace, 1)
1581+
reprs.append(text_repr)
1582+
15271583
varname = get_varname(self.__dabest_obj)
15281584
lastline = "To get the results of all valid statistical tests, " +\
15291585
"use `{}.{}.statistical_tests`".format(varname, self.__effect_size)
@@ -1849,7 +1905,7 @@ def plot(self, color_col=None,
18491905
if hasattr(self, "results") is False:
18501906
self.__pre_calc()
18511907

1852-
if self.__var2:
1908+
if self.__delta2:
18531909
color_col = self.__second
18541910

18551911
if self.__proportional:
@@ -1934,14 +1990,24 @@ def ci(self):
19341990
"""
19351991
return self.__ci
19361992

1993+
@property
1994+
def first(self):
1995+
return self.__first
1996+
1997+
19371998
@property
19381999
def second(self):
19392000
return self.__second
19402001

19412002

19422003
@property
1943-
def var2(self):
1944-
return self.__var2
2004+
def experiment(self):
2005+
return self.__experiment
2006+
2007+
2008+
@property
2009+
def delta2(self):
2010+
return self.__delta2
19452011

19462012

19472013
@property

0 commit comments

Comments
 (0)