如何计算一个100万列CSV中两列的相关性



场景:

  • 我有一个CSV;年龄";,和一百万其他列。我想找到最与年龄相关
  • 行数很低,比方说不到1000行
  • 这是用Python编写的更大解决方案的一部分,但它不一定是Python
  • 像大多数事情一样,我希望在代码可读性和性能之间取得平衡
  • 在下面的例子中,为了简单起见,我只看了一列。真正的解决方案可能会使用对所有列的多处理

我下面的代码可以工作,但可以理解的是,CSV存储为非常(非常!(宽的Pandas数据帧,速度很慢。

如果是你,你会怎么做?

cmdline:python mycode.py myfile.csv columnname-to-measure

import pandas as pd
from scipy import stats   
import os,sys
if __name__=="__main__":

_DATAFILE = sys.argv[1]
##Sample tiny datafile

#Age,m1,m2,m3
#35,0.00234,0.1,1
#30,0.0034,0.2,2
#40,0.0013,0.3,4
_MEASURE=sys.argv[2]
print("Parsing file %s" %(_DATAFILE))

df = pd.read_csv(_DATAFILE)
print(f"Corellating {_MEASURE} with Age")
all =df[['Age',_MEASURE]].copy()
allna=all[all[_MEASURE].notna()]
pearson_coef, p_value = stats.pearsonr( allna['Age'].values,allna[_MEASURE].values)
print(pearson_coef,p_value)

  1. 最好一次读取所有列并计算所有相关性,这样就可以避免多次读取文件。或者,使用诸如镶木地板之类的列式存储来存储文件,这样您就只能读取所需的列。查看pandas.read_parquet和df.to_parquet.

  2. 使用pandas内置的关联方法往往更快(底层numpy实现(。https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html

  3. 我不认为多处理会带来太多的速度,因为你的瓶颈是csv IO时间,而不是相关性计算时间。要么一次性读取文件,要么使用镶木地板或其他类型。

对于您的用例来说,使用pandas.DataFrame.corr的速度太慢了吗?它会计算出一堆不必要的相关性,但我会从那里开始。如果它太慢,那么你可以试试numpy.corrcoef。我将这两个数据与您的示例数据进行了比较:

data = [[35,0.00234,0.1,1],
[30,0.0034,0.2,2],
[40,0.0013,0.3,4]]
df = pd.DataFrame(data, columns=['Age', 'm1', 'm2', 'm3'])
np_data = df.to_numpy()

在Jupyter实验室环境中用%timeit魔术功能计时:

%timeit df.corr()

得到CCD_ 5。尝试numpy路由:

%timeit np.corrcoef(np_data, rowvar=False)

得到CCD_ 7。所以np.corrcoef要快一点。

为了与scipy.stats.pearsonr进行比较,我在一个函数中封装了一个列迭代策略,用于定时:

def orig(df):
for col in df.columns:
pearson_coef, p_value = stats.pearsonr(df['Age'], df[col])

如果我们计时:

%timeit orig(df)

我们得到了450 µs ± 46.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each),所以pandas.DataFrame.corrnumpy.corrcoef都更快,尽管必须计算不必要的相关性。

最新更新