【问题标题】:Populate with new value(s) to a fixed-shape numpy array filled with zeros用新值填充到一个用零填充的固定形状的 numpy 数组
【发布时间】:2020-06-02 10:39:42
【问题描述】:

鉴于numpy 数组是连续存储的,如果我们尝试对它使用appendextend,那么这不是就地发生,而是一个新的创建数组的副本,并为appendextend 连续出现提供足够的“空间”(请参阅​​https://stackoverflow.com/a/13215559/3286832)。

为了避免这种情况,假设我们有幸知道我们希望数组具有的具体元素数量,我们可以创建一个 固定大小的 numpy 数组带零

import numpy as np

a = np.zeros(shape=(100,))  # [0. 0. 0. ... 0. 0. 0.]

假设我们想通过就地编辑这个数组,每次都用一个新值来填充这个数组的每个元素(例如,由用户提供):: p>

pos = 0
a[pos] = 0.002              # [0.002 0. 0. ... 0. 0. 0.]

pos = pos + 1
a[pos] = 0.101              # [0.002 0.101 0. ... 0. 0. 0.]

# etc.

pos = -1
a[pos] = 42.00              # [0.002 0.101 ... ... ... 42.]

问题:

有没有办法跟踪下一个可用位置 pos(即先前未填充新输入值的最后一个位置),而不是每次手动递增 pos

有没有办法在numpy 中有效地实现这一点,最好是?或者有没有办法在另一个 Python 库中实现这一点(例如 scipyPandas)?

(根据 cmets 和初始答案编辑了问题,其中说明我的初始问题措辞不清楚 - 希望现在更清楚)

【问题讨论】:

  • 你的问题有点混乱。在您的示例代码中,您没有向数组“附加”任何内容。 “追加”意味着添加超出现有数组边界的值。相反,您正在更改数组中已经为它们分配空间的值。因此,不需要进行重新分配。
  • @jussinurminen 你说得对,我误用了“追加”和“扩展”这两个词。我将编辑我的问题以删除这些问题,并明确表示我只想在这个固定大小实例化的零数组中一一插入新值。
  • 我仍然不确定你想要完成什么。您的示例代码很好;它会更改数组中的现有值。你想做点别的吗?
  • @jussinurminen 我刚刚根据您的 cmets 和初步答案编辑了我的问题,使其更清晰 - 希望它更清晰。
  • 如果你想将numpy与一个预分配的数组一起使用,你需要跟踪pos。否则,没有办法知道之前写了哪些位置。 (当然,您可以尝试使用诸如np.nan 之类的特殊值预分配数组来跟踪未写入位置的技巧,但这比跟踪索引更笨拙)。如果您想要更简单的代码,另一种技术可能是使用 Python 列表来收集值(使用 .append 方法),然后将其转换为 numpy 数组。

标签: python python-3.x numpy numpy-ndarray


【解决方案1】:

实际上,您的问题仍然让我感到困惑。您如何定义要插入到新位置的新值?它来自您的代码之外吗?你的数组有所有的新值,还是只有其中的一部分?

也许,您可以使用numpy 中的切片,它们正是用于快速更新数组,但是,我不确定这是否是您想要做的。

为您提供一些示例:

>>> import numpy as np
>>> a = np.zeros(shape=(10,))
>>> a
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
>>> a[3:6] += 1
>>> a
array([0., 0., 0., 1., 1., 1., 0., 0., 0., 0.])
>>> a[:4] += .001
>>> a
array([1.000e-03, 1.000e-03, 1.000e-03, 1.001e+00, 1.000e+00, 1.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00])
>>> a[3:5] = [2, 1]
>>> a
array([1.e-03, 1.e-03, 1.e-03, 2.e+00, 1.e+00, 1.e+00, 0.e+00, 0.e+00,
       0.e+00, 0.e+00])
>>>

【讨论】:

  • 我刚刚根据您的 cmets 和最初的答案编辑了我的问题,使其更清晰 - 希望它更清晰。
  • 正如我所说,在这种情况下,您可以通过拼接来节省批量更新数组的时间。
  • 是的,当我提前知道(至少部分)新输入的值时,这很有用。
【解决方案2】:

如果我理解正确,您需要某种循环缓冲区。 Python 有collections.deque 用于此目的。

Here 是我使用h5py 自定义实现的循环缓冲区,但您可以将其更改为numpy

更新:正如 cmets 中已经提到的,开箱即用不可能跟踪 np.array 的更改。相反,您可以实现自己的类并在那里跟踪所有必要的更改(请参阅我的 implementation 作为示例,即连接数组以扩展其大小)。我建议你使用 python list 如果你需要追加或deque 如果你需要固定大小。然后可以将这两个数组转换为np.array

【讨论】:

  • 我刚刚根据您的 cmets 和最初的答案编辑了我的问题,使其更清晰 - 希望它更清晰。
猜你喜欢
  • 2017-10-24
  • 2015-08-09
  • 1970-01-01
  • 2016-11-06
  • 2018-10-05
  • 2016-06-15
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
相关资源
最近更新 更多