【问题标题】:How to improve computational efficiency of correlation analysis using scipy on big dataframe如何在大数据帧上使用 scipy 提高相关分析的计算效率
【发布时间】:2020-11-10 13:56:31
【问题描述】:

我有几个大数据帧 (12222 X 400000),我需要在其上使用 scipy 计算 Pearson 相关性。大数据帧是通过连接其他两个数据帧生成的。例如,在这里我可以展示类似于我的大数据框的玩具数据集。

import pandas as pd,numpy as np
from scipy.stats import pearsonr

np.random.seed([3,1415])
cols = ['A_p','B_p','C_p','D_p','E_p','F_p','N_p','M_p','O_p','Q_p']
ind2 = ['sap1','luf','tur']

df1  = pd.DataFrame(np.random.randint(10, size=(3, 10)), columns=cols,index=ind2)
cols = ['G_l','I_l','J_l','K_l','L_l','M_l','R_l']
df2  = pd.DataFrame(np.random.randint(20, size=(3, 7)), columns=cols,index=ind2)
df   = pd.concat([df1,df2],axis =1)
df
 A_p    B_p C_p D_p E_p F_p N_p M_p O_p Q_p G_l I_l J_l K_l L_l M_l R_l
sap1    0   2   7   3   8   7   0   6   8   6   11  7   12  6   4   7   18
luf 0   2   0   4   9   7   3   2   4   3   14  6   6   14  18  8   10
tur 3   6   7   7   4   5   3   7   5   9   5   15  4   15  13  7   6  

进行相关性检验的函数如下,

def correlation_analysis(lncRNA_PC_T):
    """
    Function for correlation analysis
    """
    correlations = pd.DataFrame()
    for p in [column for column in df.columns if '_p' in column]: 
        for l in [column for column in df.columns if '_l' in column]:
                    correlations = correlations.append(pd.Series(pearsonr(df[p],df[l]),index=['PCC', 'p-value'],name=p + '_' + l)
    
              
    return(correlations)

该函数在小数据帧上表现良好。然而,在上述大小的大数据帧上,完成相关性的计算需要很长时间。

我尝试制作小块数据框(df1df2)并尝试运行数据框列表。例如,如下所示,

n        = 2
list_df1 =  [df1.iloc[:, i:i+n] for i in range(0, df1.shape[1], n)]
list_df2 =  [df2.iloc[:, i:i+n] for i in range(0, df2.shape[1], n)]

然后,我将上面的列表传递给我的函数,如下所示,

def correlation(list_df1,list_df2):
    correlations = pd.DataFrame()
    for dfs,dfs2 in zip(list_df1,list_df2):
        DF = pd.concat([dfs,dfs2])
        df = DF.set_index("Gene_id").T
        for p in [column for column in df.columns if '_p' in column]:
            for l in [column for column in df.columns if '_l' in column]:
                 correlations = correlations.append(pd.Series(pearsonr(df[p],df[l]),index=['PCC', 'p-value'],name= p + '_' + l))    

   return correlations

datafrme 的输出应给出字符串_p_l 的所有列之间的成对相关性。比如像这样,

PCC p-value
A_p_G_l -0.944911   0.212296
A_p_I_l 0.994850    0.064639
A_p_J_l -0.693375   0.512246
A_p_K_l 0.585206    0.602027
A_p_L_l 0.162758    0.895922
... ... ...
Q_p_J_l -0.240192   0.845579
Q_p_K_l 0.101361    0.935361
Q_p_L_l -0.352381   0.770744
Q_p_M_l -0.866025   0.333333
Q_p_R_l -0.327327   0.787704

当前函数需要 12 多个小时才能完成大小为 1222 X 6222 的数据框。因此,有效的解决方案将非常有帮助。欢迎任何建议。 谢谢!

【问题讨论】:

    标签: python pandas numpy scipy correlation


    【解决方案1】:

    你可以看看dask,它是为分析大数据集而设计的,支持pandas,并带有多线程支持。我在您示例的扩展版本 (21x18) 上对其进行了测试,结果显示计算时间略有减少。

    correlation_analysis w/o dask 0.767 sec 
    correlation_analysis w dask 0.707 sec 
    

    dask 还提供了自己的相关计算例程https://docs.dask.org/en/latest/array-api.html?#dask.array.corrcoef

    如果要关联的两个变量 (_p, _l) 在两个数据帧中,是否需要连接它们?循环遍历两个数据帧而不是一个合并数据帧也减少了计算时间。

    def correlation_analysis2(lncRNA_PC_T):
        """
        Function for correlation analysis
        """
        correlations = pd.DataFrame()
      for p in df1:
            for l in df2:
                correlations = correlations.append(pd.Series(pearsonr(df1[p],df2[l]),index=['PCC', 'p-value'],name=p + '_' + l))
    
    correlation_analysis with 2 df  0.723 sec
    

    您可以查看https://numpy.org/doc/stable/reference/arrays.nditer.html 如何进一步优化您的循环。

    进一步的可能性可能是使用一些 JIT 编译器(即pypynumba),但效果可能仅在较大的测试样本中可见。

    【讨论】:

    • 感谢您的建议,我从未使用过dask
    • 使用单独的数据帧的解决方案并没有提高任何速度。也许dask 可以提供帮助。我会试试的。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 2010-10-15
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    相关资源
    最近更新 更多