简体   繁体   English

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

[英]Replace values of a numpy index array with values of a list

Suppose you have a numpy array and a list: 假设你有一个numpy数组和一个列表:

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

I'd like to replace values in an array, so that 1 is replaced by 0, and 2 by 10. 我想替换数组中的值,以便将1替换为0,将2替换为10。

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

But using this solution: 但使用此解决方案:

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

Throws me an error: 给我一个错误:

ValueError: assignment destination is read-only

I guess that's because I can't really write into a numpy array. 我想这是因为我无法写入一个numpy数组。

PS The actual size of the numpy array is 514 by 504 and of the list is 8. PS numpy数组的实际大小是514乘504,列表是8。

好吧,我想你需要的是什么

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

Read-only array in numpy can be made writable: numpy中的只读数组可以写入:

nArray.flags.writeable = True

This will then allow assignment operations like this one: 这将允许像这样的赋值操作:

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

The real problem was not assignment itself but the writable flag. 真正的问题不是赋值本身,而是可写标志。

Instead of replacing the values one by one, it is possible to remap the entire array like this: 不是逐个替换值,而是可以像这样重新映射整个数组:

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

yields 产量

[[ 0 10]
 [10  0]]

Credit for the above idea goes to @JoshAdel . 上述想法归功于@JoshAdel It is significantly faster than my original answer: 它明显快于我原来的答案:

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())

I benchmarked the two versions this way: 我用这种方式对两个版本进行了基准测试

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

I found another solution with the numpy function place . 我发现与numpy的功能另一种解决方案place (Documentation here ) 这里的文件)

Using it on your example: 在你的例子中使用它:

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

You can also use np.choose(idx, vals) , where idx is an array of indices that indicate which value of vals should be put in their place. 您还可以使用np.choose(idx, vals) ,其中idx是表明其价值指数的阵列vals应放在自己的位置。 The indices must be 0-based, though. 但是,索引必须是基于0的。 Also make sure that idx has an integer datatype. 还要确保idx具有整数数据类型。 So you would only need to do: 所以你只需要这样做:

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

I was unable to set the flags, or use a mask to modify the value. 我无法设置标志,或使用掩码来修改值。 In the end I just made a copy of the array. 最后我只是制作了一个数组的副本。

a2 = np.copy(a)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM