25

假设你有一个 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 数组。

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

4

6 回答 6

34

好吧,我想你需要的是

a[a==2] = 10 #replace all 2's with 10's
于 2012-11-26T20:19:31.093 回答
25

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

nArray.flags.writeable = True

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

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

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

于 2015-10-29T10:05:51.390 回答
24

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

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]]

上述想法归功于@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
于 2012-11-26T20:29:01.740 回答
2

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

在您的示例中使用它:

>>> 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]])
于 2017-01-12T14:44:32.597 回答
1

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

np.choose(a.astype(np.int32) - 1, b)
于 2017-11-29T19:55:19.493 回答
1

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

a2 = np.copy(a)
于 2019-02-07T14:16:19.057 回答