在列表中查找列表之间的相关性的效率问题
Efficiency issues with finding correlations between lists inside lists
如果我有两个小列表,我想找到 list1 中的每个列表与 list2 中的每个列表之间的相关性,我可以做到这一点
from scipy.stats import pearsonr
list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
list2 = [[10,20,30],[40,50,60],[77,78,79],[80,78,56]]
corrVal = []
for i in list1:
for j in list2:
corrVal.append(pearsonr(i,j)[0])
print(corrVal)
OUTPUT: [1.0, 1.0, 1.0, -0.90112711377916588, 1.0, 1.0, 1.0, -0.90112711377916588, 1.0, 1.0, 1.0, -0.90112711377916588, 1.0, 1.0, 1.0, -0.90112711377916588]
结果很好……差不多。 (编辑:刚刚注意到我上面的相关输出似乎给出了正确的答案,但它们重复了 4 次。不确定为什么这样做)
然而,对于列表中包含 1000 多个值的较大数据集,我的代码会无限期冻结,不会输出任何错误,因此我每次都强制退出 IDE。我在这里滑倒的任何想法?不确定 pearsonr 函数可以处理的数量是否存在固有限制,或者我的编码是否导致了问题。
进行相同的计算,但将值收集在 4x4 数组中:
In [1791]: res=np.zeros((4,4))
In [1792]: for i in range(4):
...: for j in range(4):
...: res[i,j]=stats.pearsonr(list1[i],list2[j])[0]
...:
In [1793]: res
Out[1793]:
array([[ 1. , 1. , 1. , -0.90112711],
[ 1. , 1. , 1. , -0.90112711],
[ 1. , 1. , 1. , -0.90112711],
[ 1. , 1. , 1. , -0.90112711]])
除 list2
的最后一个元素外,所有子列表都是相关的(例如 [1,2,3]*n
)。
我可以看到随着 2 个列表变长,速度会减慢的地方。我不知道 pearsonr
计算对输入的长度有多敏感。
pearsonr
代码看起来很直接,没有循环来减慢它的速度。如果您可以跳过 p
值,可能会更快;事先将每个子列表转换为零均值数组也可能会减少计算时间。
更改 j
迭代以避免重新计算下三角可能也有帮助
for j in range(i,4):
scipy模块scipy.spatial.distance
includes a distance function known as Pearson's distance, which is simply 1 minus the correlation coefficient. By using the argument metric='correlation'
in scipy.spatial.distance.cdist
,您可以高效地计算两个输入中每对向量的皮尔逊相关系数。
这是一个例子。我将修改您的数据,使系数更加多样化:
In [96]: list1 = [[1, 2, 3.5], [4, 5, 6], [7, 8, 12], [10, 7, 10]]
In [97]: list2 = [[10, 20, 30], [41, 51, 60], [77, 80, 79], [80, 78, 56]]
所以我们知道会发生什么,这里是使用 scipy.stats.pearsonr
:
计算的相关系数
In [98]: [pearsonr(x, y)[0] for x in list1 for y in list2]
Out[98]:
[0.99339926779878296,
0.98945694873927104,
0.56362148019067804,
-0.94491118252306794,
1.0,
0.99953863896044937,
0.65465367070797709,
-0.90112711377916588,
0.94491118252306805,
0.93453339271427294,
0.37115374447904509,
-0.99339926779878274,
0.0,
-0.030372836961539348,
-0.7559289460184544,
-0.43355498476205995]
在数组中查看更方便:
In [99]: np.array([pearsonr(x, y)[0] for x in list1 for y in list2]).reshape(len(list1), len(list2))
Out[99]:
array([[ 0.99339927, 0.98945695, 0.56362148, -0.94491118],
[ 1. , 0.99953864, 0.65465367, -0.90112711],
[ 0.94491118, 0.93453339, 0.37115374, -0.99339927],
[ 0. , -0.03037284, -0.75592895, -0.43355498]])
这是使用 cdist
:
计算的相同结果
In [100]: from scipy.spatial.distance import cdist
In [101]: 1 - cdist(list1, list2, metric='correlation')
Out[101]:
array([[ 0.99339927, 0.98945695, 0.56362148, -0.94491118],
[ 1. , 0.99953864, 0.65465367, -0.90112711],
[ 0.94491118, 0.93453339, 0.37115374, -0.99339927],
[ 0. , -0.03037284, -0.75592895, -0.43355498]])
使用 cdist
比在嵌套循环中调用 pearsonr
快 多 。这里我将使用两个数组,data1
和 data2
,每个数组的大小为 (100, 10000):
In [102]: data1 = np.random.randn(100, 10000)
In [103]: data2 = np.random.randn(100, 10000)
我将使用 ipython
中方便的 %timeit
命令来测量执行时间:
In [104]: %timeit c1 = [pearsonr(x, y)[0] for x in data1 for y in data2]
1 loop, best of 3: 836 ms per loop
In [105]: %timeit c2 = 1 - cdist(data1, data2, metric='correlation')
100 loops, best of 3: 4.35 ms per loop
嵌套循环为 836 毫秒,cdist
为 4.35 毫秒。
如果我有两个小列表,我想找到 list1 中的每个列表与 list2 中的每个列表之间的相关性,我可以做到这一点
from scipy.stats import pearsonr
list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
list2 = [[10,20,30],[40,50,60],[77,78,79],[80,78,56]]
corrVal = []
for i in list1:
for j in list2:
corrVal.append(pearsonr(i,j)[0])
print(corrVal)
OUTPUT: [1.0, 1.0, 1.0, -0.90112711377916588, 1.0, 1.0, 1.0, -0.90112711377916588, 1.0, 1.0, 1.0, -0.90112711377916588, 1.0, 1.0, 1.0, -0.90112711377916588]
结果很好……差不多。 (编辑:刚刚注意到我上面的相关输出似乎给出了正确的答案,但它们重复了 4 次。不确定为什么这样做)
然而,对于列表中包含 1000 多个值的较大数据集,我的代码会无限期冻结,不会输出任何错误,因此我每次都强制退出 IDE。我在这里滑倒的任何想法?不确定 pearsonr 函数可以处理的数量是否存在固有限制,或者我的编码是否导致了问题。
进行相同的计算,但将值收集在 4x4 数组中:
In [1791]: res=np.zeros((4,4))
In [1792]: for i in range(4):
...: for j in range(4):
...: res[i,j]=stats.pearsonr(list1[i],list2[j])[0]
...:
In [1793]: res
Out[1793]:
array([[ 1. , 1. , 1. , -0.90112711],
[ 1. , 1. , 1. , -0.90112711],
[ 1. , 1. , 1. , -0.90112711],
[ 1. , 1. , 1. , -0.90112711]])
除 list2
的最后一个元素外,所有子列表都是相关的(例如 [1,2,3]*n
)。
我可以看到随着 2 个列表变长,速度会减慢的地方。我不知道 pearsonr
计算对输入的长度有多敏感。
pearsonr
代码看起来很直接,没有循环来减慢它的速度。如果您可以跳过 p
值,可能会更快;事先将每个子列表转换为零均值数组也可能会减少计算时间。
更改 j
迭代以避免重新计算下三角可能也有帮助
for j in range(i,4):
scipy模块scipy.spatial.distance
includes a distance function known as Pearson's distance, which is simply 1 minus the correlation coefficient. By using the argument metric='correlation'
in scipy.spatial.distance.cdist
,您可以高效地计算两个输入中每对向量的皮尔逊相关系数。
这是一个例子。我将修改您的数据,使系数更加多样化:
In [96]: list1 = [[1, 2, 3.5], [4, 5, 6], [7, 8, 12], [10, 7, 10]]
In [97]: list2 = [[10, 20, 30], [41, 51, 60], [77, 80, 79], [80, 78, 56]]
所以我们知道会发生什么,这里是使用 scipy.stats.pearsonr
:
In [98]: [pearsonr(x, y)[0] for x in list1 for y in list2]
Out[98]:
[0.99339926779878296,
0.98945694873927104,
0.56362148019067804,
-0.94491118252306794,
1.0,
0.99953863896044937,
0.65465367070797709,
-0.90112711377916588,
0.94491118252306805,
0.93453339271427294,
0.37115374447904509,
-0.99339926779878274,
0.0,
-0.030372836961539348,
-0.7559289460184544,
-0.43355498476205995]
在数组中查看更方便:
In [99]: np.array([pearsonr(x, y)[0] for x in list1 for y in list2]).reshape(len(list1), len(list2))
Out[99]:
array([[ 0.99339927, 0.98945695, 0.56362148, -0.94491118],
[ 1. , 0.99953864, 0.65465367, -0.90112711],
[ 0.94491118, 0.93453339, 0.37115374, -0.99339927],
[ 0. , -0.03037284, -0.75592895, -0.43355498]])
这是使用 cdist
:
In [100]: from scipy.spatial.distance import cdist
In [101]: 1 - cdist(list1, list2, metric='correlation')
Out[101]:
array([[ 0.99339927, 0.98945695, 0.56362148, -0.94491118],
[ 1. , 0.99953864, 0.65465367, -0.90112711],
[ 0.94491118, 0.93453339, 0.37115374, -0.99339927],
[ 0. , -0.03037284, -0.75592895, -0.43355498]])
使用 cdist
比在嵌套循环中调用 pearsonr
快 多 。这里我将使用两个数组,data1
和 data2
,每个数组的大小为 (100, 10000):
In [102]: data1 = np.random.randn(100, 10000)
In [103]: data2 = np.random.randn(100, 10000)
我将使用 ipython
中方便的 %timeit
命令来测量执行时间:
In [104]: %timeit c1 = [pearsonr(x, y)[0] for x in data1 for y in data2]
1 loop, best of 3: 836 ms per loop
In [105]: %timeit c2 = 1 - cdist(data1, data2, metric='correlation')
100 loops, best of 3: 4.35 ms per loop
嵌套循环为 836 毫秒,cdist
为 4.35 毫秒。