Python生成滚动窗口以计算相关性
我有一个大熊猫数据框(97165行和2列),我想计算并保存每100行这些列之间的相关性,我想这样做: 第1个相关性-->从0到100的行-->corr=0.265 第二个相关性-->从1到101的行-->corr=0.279 第三个相关性-->行从2到102-->corr=0.287 每个值都必须存储并在绘图中显示,所以我必须将所有这些值保存在列表或类似的东西中 我一直在阅读有关滚动窗口的熊猫文档 但我什么都没能做到。 我尝试生成一个简单的循环以获得一些结果,但我遇到了内存问题,我尝试的代码是:Python生成滚动窗口以计算相关性,python,pandas,numpy,Python,Pandas,Numpy,我有一个大熊猫数据框(97165行和2列),我想计算并保存每100行这些列之间的相关性,我想这样做: 第1个相关性-->从0到100的行-->corr=0.265 第二个相关性-->从1到101的行-->corr=0.279 第三个相关性-->行从2到102-->corr=0.287 每个值都必须存储并在绘图中显示,所以我必须将所有这些值保存在列表或类似的东西中 我一直在阅读有关滚动窗口的熊猫文档 但我什么都没能做到。 我尝试生成一个简单的循环以获得一些结果,但我遇到了内存问题,我尝试的代码是:
lcl = 100
a = []
for i in range(len(tabla)):
x = tabla.iloc[i:lcl, [0]]
y = tabla.iloc[i:lcl, [1]]
z = x['2015_Avion'].corr(y['2015_Hotel'])
a.append(z)
lcl += 1
有什么建议吗?我们可以通过处理阵列数据来优化内存和性能 方法#1 首先,让我们使用数组解决方案来获得两个
1D
数组之间对应元素的相关系数。这将基本上受到启发,看起来像这样-
def corrcoeff_1d(A,B):
# Rowwise mean of input arrays & subtract from input arrays themeselves
A_mA = A - A.mean(-1,keepdims=1)
B_mB = B - B.mean(-1,keepdims=1)
# Sum of squares
ssA = np.einsum('i,i->',A_mA, A_mA)
ssB = np.einsum('i,i->',B_mB, B_mB)
# Finally get corr coeff
return np.einsum('i,i->',A_mA,B_mB)/np.sqrt(ssA*ssB)
现在,要使用它,请在数组数据上使用相同的循环-
lcl = 100
ar = tabla.values
N = len(ar)
out = np.zeros(N)
for i in range(N):
out[i] = corrcoeff_1d(ar[i:i+lcl,0], ar[i:i+lcl,1])
我们可以通过预先计算滚动平均值来进一步优化性能,滚动平均值用于使用卷积计算corrcoff\u 1d
中的A_mA
,但首先让我们排除内存错误
方法#2
这是一种几乎矢量化的方法,因为我们将矢量化大多数迭代,除了末尾没有适当窗口长度的剩余切片。循环计数将从97165
减少到lcl-1
,即仅99
lcl = 100
ar = tabla.values
N = len(ar)
out = np.zeros(N)
col0_win = strided_app(ar[:,0],lcl,S=1)
col1_win = strided_app(ar[:,1],lcl,S=1)
vectorized_out = corr2_coeff_rowwise(col0_win, col1_win)
M = len(vectorized_out)
out[:M] = vectorized_out
for i in range(M,N):
out[i] = corrcoeff_1d(ar[i:i+lcl,0], ar[i:i+lcl,1])
辅助函数-
# https://stackoverflow.com/a/40085052/ @ Divakar
def strided_app(a, L, S ): # Window len = L, Stride len/stepsize = S
nrows = ((a.size-L)//S)+1
n = a.strides[0]
return np.lib.stride_tricks.as_strided(a, shape=(nrows,L), strides=(S*n,n))
# https://stackoverflow.com/a/41703623/ @Divakar
def corr2_coeff_rowwise(A,B):
# Rowwise mean of input arrays & subtract from input arrays themeselves
A_mA = A - A.mean(-1,keepdims=1)
B_mB = B - B.mean(-1,keepdims=1)
# Sum of squares across rows
ssA = np.einsum('ij,ij->i',A_mA, A_mA)
ssB = np.einsum('ij,ij->i',B_mB, B_mB)
# Finally get corr coeff
return np.einsum('ij,ij->i',A_mA,B_mB)/np.sqrt(ssA*ssB)
NaN填充数据的相关性 下面列出了用于计算一维阵列和行相关值之间相关性的基于Pandas的相关计算的NumPy解决方案 1) 两个一维阵列之间的标量相关值-
def nancorrcoeff_1d(A,B):
# Get combined mask
comb_mask = ~(np.isnan(A) & ~np.isnan(B))
count = comb_mask.sum()
# Rowwise mean of input arrays & subtract from input arrays themeselves
A_mA = A - np.nansum(A * comb_mask,-1,keepdims=1)/count
B_mB = B - np.nansum(B * comb_mask,-1,keepdims=1)/count
# Replace NaNs with zeros, so that later summations could be computed
A_mA[~comb_mask] = 0
B_mB[~comb_mask] = 0
ssA = np.inner(A_mA,A_mA)
ssB = np.inner(B_mB,B_mB)
# Finally get corr coeff
return np.inner(A_mA,B_mB)/np.sqrt(ssA*ssB)
2) 两个2D
数组(m,n)
之间的行相关,为我们提供一个1D
形状数组(m,)
-
您提到尝试
滚动
。这到底出了什么问题?这对我很有用:
my_res = tabla['2015_Avion'].rolling(100).corr(tabla['2015_Hotel'])
my_res
将具有NaN
值,直到其100
th值,因此my_res[99]
应该是两列的行0
和行99
元素之间的相关性,这将由仅应用于子集的pandas
corr
函数返回my_res[100]
是行1
和行100
元素之间的相关性。输入数据框中有什么?用最少的代表性数据制作样本?另外,您在哪一步得到内存错误?排序的整数值大多数输出值是nan或0,在我的表中只有0到10之间的整数值。因此我不明白为什么我得到nan/0值。您是从某种csv读取的吗?是否可能某些值具有转义字符或导致问题的非ascii字符?我希望它会抛出一个错误,但这取决于corr()的工作方式。我现在无法使用一些随机整数重新创建问题。我使用read_pickle读取文件,格式是bz2。我查看了数据集,但没有发现任何奇怪的地方。我没有使用python中的read_pickle或bz2的经验。尝试打印(repr())某些值,以检查是否出现任何奇怪的情况(print()可能无法捕获转义字符等)-例如,在窗口中提供NaN相关性的所有值上。如果my和Divakar的解决方案都提供0/NaN,我强烈建议查看数据本身-问题几乎肯定存在。你可以自己检查,也可以根据Divakar的建议发布一个示例。谢谢你的帮助,这很好,但我遇到了与其他方法相同的问题,前77个值很好,但之后所有值都是0或nan。idk为什么,但这一切都在发生solutions@WinterZ正如我在前面的评论中所说-。有一个bz2格式的样本,在我所有的方法中都包含10k行,就像在你的方法中一样,因为corr行77我得到了nan值…@WinterZ So?这两种解决方案现在都起作用了吗?问题是我对数据进行了排序,所以有很多重复值。您的解决方案非常好,但在我的例子中,我得到了nan值,因为这行代码:A_mA=A-A.mean(-1,keepdims=1),例如,所有用3填充的向量使A_mA等于0,并且当该值为0时,相关性公式不起作用。多谢各位!
my_res = tabla['2015_Avion'].rolling(100).corr(tabla['2015_Hotel'])