Python pandas函数应用于所有行对的组合

8
我正在尝试在pandas数据框的所有成对行组合上运行一个函数(相关性):
stats = dict()
for l in itertools.combinations(dat.index.tolist(),2):
    stats[l] = pearsonr(dat.loc[l[0],:], dat.loc[l[1],:]) # stores (r, p)

当然,这种方法非常慢,我在想如何通过使用类似于apply()之类的东西来实现等效操作。

注意:我知道可以直接使用pandas corr()函数查找数据框的相关性,但它不返回相关的p值(这是我需要进行过滤的目的)。


1
如果您查看pearsonr的源代码,您会发现只需要几行代码就可以计算出相关系数的p值。制作一个可以用于.apply(function)函数应该不难。 - Primer
考虑将您的标题更改为更具体的内容 :) - Ciprian Tomoiagă
1个回答

3
这应该能加速一些。定义一个名为Pearson的函数,从Primer链接中修改而来:
def Pearson(r, n=len(dat)):
    r = max(min(r, 1.0), -1.0)
    df = n - 2
    if abs(r) == 1.0:
        prob = 0.0
    else:
        t_squared = r**2 * (df / ((1.0 - r) * (1.0 + r)))
        prob = betai(0.5*df, 0.5, df/(df+t_squared))

    return (r,prob)

使用applymap函数,对dat.corr进行逐元素操作。将相关系数r传递给Pearson函数:
np.random.seed(10)
dat = pd.DataFrame(np.random.randn(5, 5))
dat[0] = np.arange(5) # seed two correlated cols
dat[1] = np.arange(5) # ^^^

dat.corr().applymap(Pearson)

    0   1   2   3   4
0   (1.0, 0.0)  (1.0, 0.0)  (0.713010395675, 0.176397305541)    (0.971681374885, 0.00569624513678)  (0.0188249871501, 0.97603269768)
1   (1.0, 0.0)  (1.0, 0.0)  (0.713010395675, 0.176397305541)    (0.971681374885, 0.00569624513678)  (0.0188249871501, 0.97603269768)
2   (0.713010395675, 0.176397305541)    (0.713010395675, 0.176397305541)    (1.0, 0.0)  (0.549623945218, 0.337230071385)    (-0.280514871109, 0.647578381153)
3   (0.971681374885, 0.00569624513678)  (0.971681374885, 0.00569624513678)  (0.549623945218, 0.337230071385)    (1.0, 0.0)  (0.176622737448, 0.77629170593)
4   (0.0188249871501, 0.97603269768)    (0.0188249871501, 0.97603269768)    (-0.280514871109, 0.647578381153)   (0.176622737448, 0.77629170593)     (1.0, 0.0)

dat很大时,使用这种方法可以看到加速,但由于逐元素操作,仍然相当缓慢。

np.random.seed(10)
dat = pd.DataFrame(np.random.randn(100, 100))

%%timeit
dat.corr().applymap(Pearson)

10 loops, best of 3: 118 ms per loop

%%timeit
stats = dict()

for l in combinations(dat.index.tolist(),2):
    stats[l] = pearsonr(dat.loc[l[0],:], dat.loc[l[1],:])

1 loops, best of 3: 1.56 s per loop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接