【问题标题】:indexing/slicing in numpy array to modify it在 numpy 数组中索引/切片以修改它
【发布时间】:2015-03-28 03:09:58
【问题描述】:

我有一个 numpy 数组 A,我想使用索引列表 B 修改其中的值。但问题是在我的切片中,我可以多次拥有数组的元素... 这个例子将更好地解释我的意思:

import numpy as np
A = np.arange(5) + 0.5
B = np.array([0, 1, 0, 2, 0, 3, 0, 4])
print A[B]

按预期返回[ 0.5 1.5 0.5 2.5 0.5 3.5 0.5 4.5]。 但是,如果我这样做:

A[B] += 1.
print A

我期望获得[ 4.5 2.5 3.5 4.5 5.5],因为第一个元素在索引向量B 中重复了4 次,但它返回[ 1.5 2.5 3.5 4.5 5.5]。 那么我该如何做我真正想做的事情呢? (不使用任何循环,因为我在非常大的数组上使用它)

【问题讨论】:

  • 不明白。您的预期结果是 [ 4.5 2.5 3.5 4.5],它只有 4 个元素,而 B 中有 5 个索引。为什么缺少一个元素?
  • 我在简单的 A(即非随机)上运行您的示例以获得一些可重复的结果:pastebin.com/mm2CcmK7 对我来说,如果我理解正确的话,它似乎工作正常。
  • @Marcin A 在我的情况下不是随机的......它是 arange(5) + 0.5 但无论如何它在您的示例中的工作方式相同,我希望得到 [15 23 34 45 56] 而不是 [12 23 34 45 56] A 的第一个元素在索引列表 B 中重复 4 次,它应该提交 4 次到 +1 操作......至少这就是我最终想要做的。知道怎么做吗?
  • 嗯,好的。现在我明白你的意思了。比检查杰米的回答。它似乎解决了这个问题。

标签: python numpy indexing slice


【解决方案1】:

为什么会发生这种情况的解释有点复杂,但基本上,“缓冲吃了你的功课”。有几种方法可以解决这个 numpy ufuncs 问题。适用于任何操作的正确方法是使用相应的 ufunc 的at method

>>> A = np.arange(5) + 0.5
>>> B = np.array([0, 1, 0, 2, 0, 3, 0, 4])
>>> np.add.at(A, B, 1)
>>> A
array([ 4.5,  2.5,  3.5,  4.5,  5.5])

这往往有点慢,所以为了尽可能快的性能,并且仅用于添加,您可以使用np.bincount

>>> A = np.arange(5) + 0.5
>>> A += np.bincount(B) * 1  # replace the 1 with the number you want to add
>>> A
array([ 4.5,  2.5,  3.5,  4.5,  5.5])

编辑

如果您要添加的是与B 长度相同的数组,那么使用bincount 的以下方法可能会比第一种方法运行得更快:

>>> A = np.arange(5) + 0.5
>>> C = np.ones_like(B)  # They are all ones, but could be anything
>>> A += np.bincount(B, weights=C)
>>> A
array([ 4.5,  2.5,  3.5,  4.5,  5.5])

【讨论】:

  • 谢谢。这实际上非常有效,但不完全符合我最终想要做的事情......我的例子很简单。如果我有另一个数组 C:C = np.arange(8),我想要做的(这不起作用,但你可以看到这一点)是沿着这些思路:A[B]+=C。所以我不只是添加单个值,而是添加一个与 B 大小相同的数组。我清楚还是混淆了?
  • 对不起,您的第一个解决方案实际上是在做这项工作......因为我想要一些高效的东西,所以我直接跳到了第二个。
  • 查看我的编辑,它可能比使用.at 来添加更快。
  • 我仍然遇到的一个问题是使用 bincount 的方法是索引数组 (B) 必须至少包含一次 A 的每个索引,否则会出现形状错误 ValueError: operands could not be broadcast together.at 方法没有这个要求。
  • 您可以使用bincountminlengthargument 来解决这个问题,所以应该使用np.bincount(B, weights=C, minlength=len(A)) 之类的方法。但正如您注意到的那样,它变得很棘手:除非这对您来说是一个瓶颈,否则正确的做法是使用 .at:它可能会在 numpy 的未来版本中变得更快,这是最近添加的。
猜你喜欢
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-30
  • 2020-04-13
  • 2015-01-21
相关资源
最近更新 更多