【问题标题】:Better way to insert elements into numpy array将元素插入 numpy 数组的更好方法
【发布时间】:2019-02-20 02:37:17
【问题描述】:

我有一个 numpy 数组,我有一个要在特定位置(不连续)插入到该数组的元素列表。索引在另一个 numpy 数组中。

target answer: [1,2,3,4,5]
original array: [1,3,5]
elements to insert: [2,4]
indices: [1,3]

numpy.insert(arr,[1,3],[2,4]) 没有给出想要的结果。它给了[1,2,3,5,4]。 有什么指点吗?

【问题讨论】:

  • 你可能不应该这样做。如果 Python 列表正在改变大小,使用它们会更有效
  • 复杂之处在于您选择的索引 - 它们是相对于原始数组还是目标。 insert2 放在original[1] 之后,将4 放在original[3] 之后。相反,您希望它们位于result[1]result[3] 插槽。
  • @roganjosh,通常多次插入列表需要从最后一个开始,因此列表的增长不会弄乱索引。在这种情况下,该迭代可以从第一次开始,因为indices 已经影响了增长。
  • @hpaulj 我认为你是对的。我一直在尝试在聊天中进行基准测试,它并不像我认为的数组那么可怕

标签: python arrays python-2.7 numpy scipy


【解决方案1】:

np.insert 中使用范围偏移索引 -

np.insert(a, add_idx - np.arange(len(add_idx)), add_val)

示例运行 -

In [20]: a
Out[20]: array([1, 3, 5])

In [21]: add_idx
Out[21]: [1, 3]

In [22]: add_val
Out[22]: [2, 4]

In [23]: np.insert(a, add_idx - np.arange(len(add_idx)), add_val)
Out[23]: array([1, 2, 3, 4, 5])

【讨论】:

  • 这是完美的。我试图在纸上追踪这一点,但我不太直观地清楚它是如何工作的,以及你是如何想出这个的。你能解释一下吗?谢谢。
【解决方案2】:

列表方法是:

In [122]: alist=[1,3,5]
In [123]: for i,j in zip([1,3],[2,4]):
     ...:     alist[i:i] = [j]
     ...:     
In [124]: alist
Out[124]: [1, 2, 3, 4, 5]

np.insert 是一个复杂的函数,根据索引输入采用不同的方法。但在这种情况下,使用布尔掩码方法:

In [126]: arr = np.array([1,3,5])
In [127]: res = np.zeros(5, int) # 5 is len(arr)+len([2,4])
In [128]: mask = res.astype(bool)
In [129]: mask[[1,3]] = True
In [130]: mask
Out[130]: array([False,  True, False,  True, False])
In [131]: res[mask] = [2,4]
In [132]: res[~mask] = arr
In [133]: res
Out[133]: array([1, 2, 3, 4, 5])

mask 定义了新值的去向,~mask 定义了原始值的去向。

insert 假定索引是相对于源数组而不是目标给出的。为了做同样的事情,必须给它[1,2],换句话说,在arr[1]arr[2]之后。 insert 会将 [1,2] 调整为 [1,3] 以使用上述屏蔽方法。 @Divakar 的答案采用您的 [1,3] 并将其转换为 insert 期望的 [1,2]。他实际上是在补偿insert 通常添加的偏移量。


如果我们使用[1,2](相对于源列表的索引),我上面使用的列表迭代是错误的。它没有考虑插入2 后列表增长的事实:

In [134]: alist=[1,3,5]
In [135]: for i,j in zip([1,2],[2,4]):
     ...:     alist[i:i] = [j]   
In [136]: alist
Out[136]: [1, 2, 4, 3, 5]

为了弥补这一点,一个常见的技巧是以相反的顺序插入:

In [137]: alist=[1,3,5]
In [138]: for i,j in zip([1,2][::-1],[2,4][::-1]):
     ...:     alist[i:i] = [j]
In [139]: alist
Out[139]: [1, 2, 3, 4, 5]

【讨论】:

    猜你喜欢
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2022-12-21
    • 1970-01-01
    • 2019-08-06
    • 2021-08-06
    • 1970-01-01
    相关资源
    最近更新 更多