我偏向于对数据帧使用 pandas 内置 corr
方法。但是,我正在尝试计算具有 45,000 列的数据框的相关矩阵。然后重复 250 次。计算正在压垮我的 ram(16 GB,mac book pro)。我正在获取有关生成的相关矩阵列的统计信息。所以我需要一列与其他所有列的相关性来计算这些统计数据。我的解决方案是计算列子集与其他所有列的相关性,但我需要一种有效的方法来执行此操作。
考虑:
import pandas as pd
import numpy as np
np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(6, 4), columns=list('ABCD'))
df
我只想计算 ['A', 'B']
corrs = df.corr()[['A', 'B']]
corrs
我将通过计算平均值或其他一些统计数据来完成它。
我不能使用我用来创建示例的代码,因为当我放大时,我没有足够的内存。执行计算时,它必须使用与所选列数成比例的内存量来计算相对于其他所有内容的相关性。
我正在寻找性能最佳的大规模解决方案。我有一个解决方案,但我正在寻找其他想法以确保我得到最好的。任何提供的答案如演示中所示返回正确答案并满足内存限制都将被我投票(我也鼓励彼此投票)。
下面是我的代码:
def corr(df, k=0, l=10):
d = df.values - df.values.mean(0)
d_ = d[:, k:l]
s = d.std(0, keepdims=True)
return pd.DataFrame(d.T.dot(d[:, k:l]) / s.T.dot(s[:, k:l]) / d.shape[0],
df.columns, df.columns[k:l])
最佳答案
使用点积计算相关性(如您的示例所示)似乎是一种不错的方法。我将描述两项改进,然后编写实现它们的代码。
改进1:拉出点积的手段
我们可以从点积中提取平均值,以避免从每个值中减去它们(类似于您从点积中提取标准差的方式,我们也会这样做)。
让x, y
是向量 n
元素。让a, b
是标量。让<x,y>
表示 x 和 y 之间的点积。
x
之间的相关性和 y
可以用点积表示
<(x-mean(x))/std(x), (y-mean(y))/std(y)> / n
要从点积中提取标准差,我们可以使用以下恒等式(就像您在上面所做的那样):
<ax, by> = a*b*<x, y>
为了从点积中提取均值,我们可以推导出另一个恒等式:
<x+a, y+b> = <x,y> + a*sum(y) + b*sum(x) + a*b*n
在 a = -mean(x), b = -mean(y)
的情况下,这简化为:
<x-mean(x), y-mean(y)> = <x, y> - sum(x)*sum(y)/n
使用这些身份,x
之间的相关性和 y
相当于:
(<x, y> - sum(x)*sum(y)/n) / (std(x)*std(y)*n)
在下面的函数中,这将使用矩阵乘法和外积来同时处理多个变量(如您的示例)。
改进 2:预先计算总和和标准差
我们可以预先计算总和和标准差,以避免每次调用函数时为所有列重新计算它们。
代码
将这两个改进放在一起,我们有以下内容(我不会说 pandas,所以它在 numpy 中):
def corr_cols(x, xsum, xstd, lo, hi):
n = x.shape[0]
return (
(np.dot(x.T, x[:, lo:hi]) - np.outer(xsum, xsum[lo:hi])/n)
/ (np.outer(xstd, xstd[lo:hi])*n)
)
# fake data w/ 10 points, 5 dimensions
x = np.random.rand(10, 5)
# precompute sums and standard deviations along each dimension
xsum = np.sum(x, 0)
xstd = np.std(x, 0)
# calculate columns of correlation matrix for dimensions 1 thru 3
r = corr_cols(x, xsum, xstd, 1, 4)
更好的代码
可以将总和和标准差的预计算和存储隐藏在闭包中,以提供更好的界面并保持主代码更简洁。在功能上,这些操作等同于前面的代码。
def col_correlator(x):
n = x.shape[0]
xsum = np.sum(x, 0)
xstd = np.std(x, 0)
return lambda lo, hi: (
(np.dot(x.T, x[:, lo:hi]) - np.outer(xsum, xsum[lo:hi])/n)
/ (np.outer(xstd, xstd[lo:hi])*n)
)
# construct function to compute columns of correlation matrix
cc = col_correlator(x)
# compute columns of correlation matrix for dimensions 1 thru 3
r = cc(1, 4)
编辑:(piRSquared)
我想将我的修改放在这篇文章中,以进一步鼓励对该答案的支持。
这是我利用此建议实现的代码。该解决方案在 pandas 和 numpy 之间来回转换。
def corr_closure(df):
d = df.values
sums = d.sum(0, keepdims=True)
stds = d.std(0, keepdims=True)
n = d.shape[0]
def corr(k=0, l=10):
d2 = d.T.dot(d[:, k:l])
sums2 = sums.T.dot(sums[:, k:l])
stds2 = stds.T.dot(stds[:, k:l])
return pd.DataFrame((d2 - sums2 / n) / stds2 / n,
df.columns, df.columns[k:l])
return corr
用例:
corr = corr_closure(df)
corr(0, 2)
关于python - 计算相关矩阵子集的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38177464/