在Python中迭代减去数组中的元素

时间:2017-03-24 20:24:40

标签: python arrays numpy iteration subtraction

我有一个很大的numpy数组。有没有办法用它下面的元素减去每个元素,并将结果存储在新的列表/数组中,而不使用循环。

我的意思的一个简单例子:

a = numpy.array([4,3,2,1])

result = [4-3, 4-2, 4-1, 3-2, 3-1, 2-1] = [1, 2, 3, 1, 2 ,1]

请注意“真实”'我正在使用的数组并不包含数字序列。这只是为了使示例简单。

我知道结果应该有(n-1)!元素,其中n是数组的大小。

有没有办法在不使用循环的情况下执行此操作,而是通过在“智能”中重复数组。办法?

谢谢!

4 个答案:

答案 0 :(得分:3)

temp = a[:, None] - a
result = temp[np.triu_indices(len(a), k=1)]

执行所有成对减法以生成temp,包括从自身中减去元素并从后面的元素中减去先前的元素,然后使用triu_indices选择我们想要的结果。 (a[:, None] adds an extra length-1 axis to a。)

请注意,几乎所有的运行时都用于从result构造temp(因为triu_indices很慢并且使用索引来选择数组的上三角形很慢)。如果您可以直接使用temp,则可以节省大量时间:

In [13]: a = numpy.arange(2000)

In [14]: %%timeit
   ....: temp = a[:, None] - a
   ....: 
100 loops, best of 3: 6.99 ms per loop

In [15]: %%timeit
   ....: temp = a[:, None] - a
   ....: result = temp[numpy.triu_indices(len(a), k=1)]
   ....: 
10 loops, best of 3: 51.7 ms per loop

答案 1 :(得分:2)

这是基于masking的广播减法后的提取方法,对于掩码创建,我们再次使用broadcasting(可以说是双broadcasting动力) -

r = np.arange(a.size)
out = (a[:, None] - a)[r[:,None] < r]

运行时测试

矢量化方法 -

# @user2357112's solution
def pairwise_diff_triu_indices_based(a):
    return (a[:, None] - a)[np.triu_indices(len(a), k=1)]

# Proposed in this post
def pairwise_diff_masking_based(a):
    r = np.arange(a.size)
    return (a[:, None] - a)[r[:,None] < r]

计时 -

In [109]: a = np.arange(2000)

In [110]: %timeit pairwise_diff_triu_indices_based(a)
10 loops, best of 3: 36.1 ms per loop

In [111]: %timeit pairwise_diff_masking_based(a)
100 loops, best of 3: 11.8 ms per loop

仔细查看相关的性能参数

让我们深入了解此设置的时间,以研究基于蒙版的方法有多少帮助。现在,为了比较,有两个部分 - 掩码创建与索引创建和基于掩码的布尔索引与基于整数的索引。

创建的面具有多少帮助?

In [37]: r = np.arange(a.size)

In [38]: %timeit np.arange(a.size)
1000000 loops, best of 3: 1.88 µs per loop

In [39]: %timeit r[:,None] < r
100 loops, best of 3: 3 ms per loop

In [40]: %timeit np.triu_indices(len(a), k=1)
100 loops, best of 3: 14.7 ms per loop

关于索引设置的掩码创建的5x改进。

布尔索引对整数索引有多大帮助?

In [41]: mask = r[:,None] < r

In [42]: idx = np.triu_indices(len(a), k=1)

In [43]: subs = a[:, None] - a

In [44]: %timeit subs[mask]
100 loops, best of 3: 4.15 ms per loop

In [45]: %timeit subs[idx]
100 loops, best of 3: 10.9 ms per loop

此处有2.5x改进。

答案 2 :(得分:1)

a = [4, 3, 2, 1]
differences = ((x - y) for i, x in enumerate(a) for y in a[i+1:])
for diff in differences:
  # do something with difference.
  pass

答案 3 :(得分:0)

结帐itertools.combinations

from itertools import combinations

l = [4, 3, 2, 1]

result = []
for n1, n2 in combinations(l, 2):
    result.append(n1 - n2)

print result

结果:

[1, 2, 3, 1, 2, 1]

combinations返回一个生成器,因此这适用于非常大的列表:)