我试图找到列表元素与列表中每个元素的列表的所有元素之间的差异。我认为这是我如何描述的?让我们使用一个例子来代替:
idx = [1, 4, 8, 10, 22]
基于this question,将元素压缩在一起就足够简单,但这会导致每个元素只进行一次成对比较,而我需要为每个元素进行多次成对比较。
我的方法是做以下事情:
diffs = [abs(i-j) for i in idx for j in idx]
但这非常低效。计算以下所有元组的差异的最有效方法是什么?
comparisons = [(1,4), (1,8), (1,10), (1, 22),
(4,8), (4,10), (4,22),
(8,10, 8,22)]
我更喜欢使用基础Python 2.7的答案,但我也想知道如何使用Numpy来做到这一点,因为我确信软件包可以让它更容易。
答案 0 :(得分:4)
你可以写一个发电机:
idx = [1, 4, 8, 10, 22]
def differences(nums):
n = len(nums)
for i in xrange(n-1):
for j in xrange(i+1,n):
yield abs(nums[i]-nums[j])
for d in differences(idx): print d
输出:
3
7
9
21
4
6
18
2
14
12
这会逐个产生差异,内存开销很小。此外,使用@RoryDaulton的想法,这并不打算计算冗余或已知为零的差异。
答案 1 :(得分:3)
请注意,您的结果实际上会包含n*n
元素。因此,如果您的长度为25,039
(如评论中所述),则必须注意不要使用这些6.3亿元素来点击MemoryError
。
一种方法是numpy并选择足够小的dtype
:
import numpy as np
arr = np.array(your_list, dtype=np.int16)
diffs = arr[:, None] - arr # this will be a 25039 x 25039 array containing your desired differences.
即使使用np.int16
,您也需要大量内存(我在这里使用的数据大小为25000):
>>> diffs.nbytes
1_250_000_000
如果您在int32
上操作,那么您将大致需要2.5GB来保存结果 - 使用long(如果您不在无限精度整数范围内,则默认为pythons)高达5GB,忽略任何python对象开销。请注意,int16
的值范围仅为−32768
to 32767
,因此如果需要,您可能需要选择更大的dtype。
除了记忆问题之外,在这些操作的效率方面没有办法打败numpy。在我的计算机上花了大约1.2秒来计算25k x 25k的差异数组。
如果您需要差异小于某个值的出现次数,那么numpy再次提供了一个简单的解决方案:
num = np.sum(np.abs(diffs) < some_value)