用列表的值替换 numpy 索引数组的值

Posted

技术标签:

【中文标题】用列表的值替换 numpy 索引数组的值【英文标题】:Replace values of a numpy index array with values of a list 【发布时间】:2012-11-14 09:04:53 【问题描述】:

假设你有一个 numpy 数组和一个列表:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
       [2, 1]])
>>> b = [0, 10]

我想替换数组中的值,所以 1 被 0 替换,2 被 10 替换。

我在这里发现了类似的问题 - http://mail.python.org/pipermail//tutor/2011-September/085392.html

但是使用这个解决方案:

for x in np.nditer(a):
    if x==1:
        x[...]=x=0
    elif x==2:
        x[...]=x=10

给我一​​个错误:

ValueError: assignment destination is read-only

我猜那是因为我无法真正写入 numpy 数组。

附: numpy 数组的实际大小为 514 x 504,列表为 8。

【问题讨论】:

【参考方案1】:

好吧,我想你需要的是

a[a==2] = 10 #replace all 2's with 10's

【讨论】:

当我这样做时,我得到“assignment destination is read-only”,你知道这是为什么吗? 这比其他解决方案简单得多,谢谢 如果我们想同时更改索引处的元素是给定 n 的倍数,我们会怎么做。像同时改变a[2],a[4],a[6]....对于n = 2.,应该怎么做?【参考方案2】:

numpy 中的只读数组可以写成可写的:

nArray.flags.writeable = True

这将允许像这样的赋值操作:

nArray[nArray == 10] = 9999 # replace all 10's with 9999's

真正的问题不是赋值本身,而是可写标志。

【讨论】:

【参考方案3】:

可以像这样重新映射整个数组,而不是一一替换值:

import numpy as np
a = np.array([1,2,2,1]).reshape(2,2)
# palette must be given in sorted order
palette = [1, 2]
# key gives the new values you wish palette to be mapped to.
key = np.array([0, 10])
index = np.digitize(a.ravel(), palette, right=True)
print(key[index].reshape(a.shape))

产量

[[ 0 10]
 [10  0]]

Credit for the above idea goes to @JoshAdel。它比我原来的答案要快得多:

import numpy as np
import random
palette = np.arange(8)
key = palette**2
a = np.array([random.choice(palette) for i in range(514*504)]).reshape(514,504)

def using_unique():
    palette, index = np.unique(a, return_inverse=True)
    return key[index].reshape(a.shape)

def using_digitize():
    index = np.digitize(a.ravel(), palette, right=True)
    return key[index].reshape(a.shape)

if __name__ == '__main__':
    assert np.allclose(using_unique(), using_digitize())

我以这种方式对这两个版本进行了基准测试:

In [107]: %timeit using_unique()
10 loops, best of 3: 35.6 ms per loop
In [112]: %timeit using_digitize()
100 loops, best of 3: 5.14 ms per loop

【讨论】:

感谢unutbu!我会接受你的回答,因为它更通用。干杯。 "index = np.digitize(a.reshape(-1,), palette)-1" 可以替换为 "index = np.digitize(a.reshape(-1,), palette) ,对=真)”,对吧? (=对吗?) @PietroBattiston:因为a 中的每个值都在palette 中,所以我认为right=True 返回相同的结果。感谢您的改进! 如果我们想改变给定 n 的倍数的索引值,例如 a[2],a[4],a[6],a[8].. ... 对于 n=2?【参考方案4】:

我找到了另一个使用 numpy 函数 place 的解决方案。 (文档here)

在您的示例中使用它:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
   [2, 1]])
>>> np.place(a, a==1, 0)
>>> np.place(a, a==2, 10)
>>> a
array([[ 0, 10],
       [10,  0]])

【讨论】:

这是完美而简单的。谢谢@Linda!【参考方案5】:

您也可以使用np.choose(idx, vals),其中idx 是一个索引数组,指示应将vals 的哪个值放在它们的位置。但是,索引必须从 0 开始。还要确保idx 具有整数数据类型。所以你只需要这样做:

np.choose(a.astype(np.int32) - 1, b)

【讨论】:

【参考方案6】:

我无法设置标志或使用掩码修改值。最后我只是复制了一个数组。

a2 = np.copy(a)

【讨论】:

以上是关于用列表的值替换 numpy 索引数组的值的主要内容,如果未能解决你的问题,请参考以下文章

用0到1之间的值替换numpy数组元素[重复]

用给定的索引替换php数组中的值

用列表中的值填充 NaN

Numpy:使用字典作为地图有效地替换二维数组中的值

Python Numpy:用另一个数组中的对应值替换一个数组中的值

使用 numpy 数组中的值从 DataFrame 创建 Pandas DataFrame 以访问数据框索引