洗牌数据帧以计算 pandas 中的 P 值的最快方法
Fastet way to shuffle a dataframe to calculate P value in pandas
我有以下数据框(数据框的实际长度要大得多):
spend_df:
var spend
1 120
2 200
1 111
1 143
1 230
2 180
2 190
2 94
2 100
1 278
这里 'var' 列告诉测试行属于哪组,我需要将 df 洗牌 1000 次以将每一行随机分配到测试的不同侧,然后 groupby 'var' 并计算来回的差异每次迭代。最后计算组间总和的差异大于实际差异的次数:
我采用以下方法:
def simulate(df):
simul_df = df.copy()
shuffled_var = simul_df.sample(frac=1)
shuffled_var.index = simul_df.index # replace shuffled series' index with the real one
simul_df['var'] = shuffled_var
simul_grouped = simul_df.groupby('var').sum()['spend']
simul_difference = simul_grouped.iloc[1] - simul_grouped.iloc[0]
return simul_difference
simulate(spend_df)
这就是我计算模拟差异比实际差异大多少倍的方法:
simulations = np.array([simulate(spend_df) for i in range(1000)])
(simulations > real_difference).mean()
这里 real_difference 是两组支出总和之间的差异(按 'var' 分组):
grouped=df.groupby('var').sum().reset_index()
real_diff=grouped.iloc[1] - grouped.iloc[0]
在这种情况下是:882-764= 118
每当我打乱数据帧时,我需要像上面那样计算新组的差异,然后我需要找出这个模拟差异有多少次超过 real_diff
这个解决方案对我来说似乎有点老套,对于这个计算 P 值的模拟任务,有没有更快或更有条理的方法?无需深入研究统计方法。
尝试 1
def gdif(df):
v, s = df.values.T
return np.diff(df.groupby('var').spend.sum().values)[0]
def shuf(df):
np.random.shuffle(df['var'].values)
return df
def sim1(df):
sdf = df.copy()
real_diff = gdif(sdf)
return (np.array([gdif(shuf(sdf)) for _ in range(1000)]) > real_diff).mean()
sim1(spend_df)
0.52900000000000003
尝试 2
还有更多numpy
def gdif2(values):
v, s = values.T
r = np.arange(v.size)
a = v.argsort()
c = s[a].cumsum()
d0 = c[np.flatnonzero(np.diff(v[a]))[0]]
return c[-1] - 2 * d0
def shuf2(v):
np.random.shuffle(v[:, 0])
return v
def sim2(df):
values = df.values
real_diff = gdif2(values)
return (np.array([gdif2(shuf2(values)) for _ in range(1000)]) > real_diff).mean()
sim2(spend_df)
0.52700000000000002
天真的时间测试
我有以下数据框(数据框的实际长度要大得多):
spend_df:
var spend
1 120
2 200
1 111
1 143
1 230
2 180
2 190
2 94
2 100
1 278
这里 'var' 列告诉测试行属于哪组,我需要将 df 洗牌 1000 次以将每一行随机分配到测试的不同侧,然后 groupby 'var' 并计算来回的差异每次迭代。最后计算组间总和的差异大于实际差异的次数:
我采用以下方法:
def simulate(df):
simul_df = df.copy()
shuffled_var = simul_df.sample(frac=1)
shuffled_var.index = simul_df.index # replace shuffled series' index with the real one
simul_df['var'] = shuffled_var
simul_grouped = simul_df.groupby('var').sum()['spend']
simul_difference = simul_grouped.iloc[1] - simul_grouped.iloc[0]
return simul_difference
simulate(spend_df)
这就是我计算模拟差异比实际差异大多少倍的方法:
simulations = np.array([simulate(spend_df) for i in range(1000)])
(simulations > real_difference).mean()
这里 real_difference 是两组支出总和之间的差异(按 'var' 分组):
grouped=df.groupby('var').sum().reset_index()
real_diff=grouped.iloc[1] - grouped.iloc[0]
在这种情况下是:882-764= 118
每当我打乱数据帧时,我需要像上面那样计算新组的差异,然后我需要找出这个模拟差异有多少次超过 real_diff
这个解决方案对我来说似乎有点老套,对于这个计算 P 值的模拟任务,有没有更快或更有条理的方法?无需深入研究统计方法。
尝试 1
def gdif(df):
v, s = df.values.T
return np.diff(df.groupby('var').spend.sum().values)[0]
def shuf(df):
np.random.shuffle(df['var'].values)
return df
def sim1(df):
sdf = df.copy()
real_diff = gdif(sdf)
return (np.array([gdif(shuf(sdf)) for _ in range(1000)]) > real_diff).mean()
sim1(spend_df)
0.52900000000000003
尝试 2
还有更多numpy
def gdif2(values):
v, s = values.T
r = np.arange(v.size)
a = v.argsort()
c = s[a].cumsum()
d0 = c[np.flatnonzero(np.diff(v[a]))[0]]
return c[-1] - 2 * d0
def shuf2(v):
np.random.shuffle(v[:, 0])
return v
def sim2(df):
values = df.values
real_diff = gdif2(values)
return (np.array([gdif2(shuf2(values)) for _ in range(1000)]) > real_diff).mean()
sim2(spend_df)
0.52700000000000002
天真的时间测试