洗牌数据帧以计算 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

天真的时间测试