我正在尝试根据子集的子集修改数组的值,但找不到执行此操作的方法。我认为这暴露了我对数组索引和子集的工作原理以及 View 是什么缺乏了解,但我无法在任何地方找到解决方案,所以我希望有人可以帮助我。
示例问题:
import numpy as np
#generate some simple data
MyArray=np.arange(20).reshape(4,5)
>>>MyArray
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
#subset 1
i=np.where(MyArray > 5)
#subset of that subset
j=np.where(MyArray[i] < 15)
>>>MyArray[i][j]
array([ 6, 7, 8, 9, 10, 11, 12, 13, 14])
太好了,这正是我所期待的!但是,如果我现在想将这些值更改为其他值,我不能:
>>>MyArray[i][j]=999
>>>MyArray[i][j]
array([ 6, 7, 8, 9, 10, 11, 12, 13, 14])
#hmmmm :(
一个可行的丑陋解决方案
我可以通过分别遍历 j
的元素来改变值,但这看起来非常笨拙且难以阅读:
#get number of elements in j
nj=np.size(j)
#loop over each element of j and modify the corresponding ith element
of MyArray
for j_it in range(0,nj):
MyArray[i[0][j[0][j_it]]][i[1][j[0][j_it]]]=999
>>>MyArray
array([[ 0, 1, 2, 3, 4],
[ 5, 999, 999, 999, 999],
[999, 999, 999, 999, 999],
[ 15, 16, 17, 18, 19]])
同样,我可以仅使用一级子集修改MyArray
:
ii=np.where((MyArray > 5) & (MyArray < 15))
MyArray[ii]=999
>>>MyArray
array([[ 0, 1, 2, 3, 4],
[ 5, 999, 999, 999, 999],
[999, 999, 999, 999, 999],
[ 15, 16, 17, 18, 19]])
那么,第一个示例哪里出错了?
注意:- 我知道我的最后一个解决方案可以很好地解决这个问题,但我的实际问题必然涉及更多数据和第二级子集(可能还有第三级...)
提前致谢,如果这是我真的应该能够从文档中自己解决的简单问题,我深表歉意:我只是没能:(
最佳答案
如您所说,您的最后一个示例解决了您的问题。您遗漏的问题是调用 MyArray[i]
创建了一个新数组,然后您使用 MyArray[i][j]
再次对其进行索引。当您尝试分配给该子集的结果时,您实际上并没有分配给 MyArray
。
要像您的第一个示例一样执行此操作,您需要像这样在一次操作中完成所有操作:
import numpy as np
#generate some simple data
MyArray=np.arange(20).reshape(4,5)
>>>MyArray
MyArray([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
#subset 1
i=np.where(MyArray > 5)
#subset of that subset
j=np.where(MyArray[i] < 15)
# Mask array subset
MyArray[i[0][j[0]], i[1][j[0]]] = 999
>>>MyArray
MyArray([[ 0, 1, 2, 3, 4],
[ 5, 999, 999, 999, 999],
[999, 999, 999, 999, 999],
[ 15, 16, 17, 18, 19]])
基本上,i
和j
都是包含数组的元组,指示哪些索引在where
语句中匹配。 i
包含两个数组,一个对应于 MyArray
中的每个维度。 j
包含一个数组,用于 i
中包含的数组的一维。您想要获取 i
中两个数组的 j[0]
元素。
希望这是有道理的。如果您有任何问题,请告诉我。
关于Python:根据多个子集改变数组元素的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48550999/