用列表的值替换 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 索引数组的值的主要内容,如果未能解决你的问题,请参考以下文章