繁体   English   中英

Python:基于多个子集更改数组元素的值

[英]Python: changing the value of array elements based on multiple subsets

我试图基于一个子集的一个子集来修改数组的值,但是我找不到一种方法。 我认为这暴露了我对数组索引和子集的工作原理以及视图的确切性的了解,但是我在任何地方都找不到解决方案,因此我希望有人可以帮助我。

问题示例:

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

基本上, ij都是包含数组的元组,这些数组指示在where语句中匹配了哪些索引。 i包含两个数组, MyArray每个维度一个。 j包含用于包含在所述阵列的单个维度一个阵列i 你想获得j[0]这两个数组的元素在i

希望这是有道理的。 如果您有任何问题,请告诉我。

尝试创建布尔数组:

condition_1 = MyArray > 5
condition_2 = MyArray < 15

然后,您可以使用按位

bools = condition1 & condition2

其值如下:

[[ False,  False,  False,  False,  False],
   [ True,  True,  True,  ...]...]

如果此类数组的长度与您要更改数据的数组的长度相同,则可以在使用索引时使用它。 但是在这里,根据单元格是否满足条件,您可以使用True或False来代替索引。

MyArray[bools] = 999

我认为@Vorticity的其他答案显然是正确的,并且是经过深思熟虑的解释,我认为不同的代码段更具可读性和可理解性。

https://docs.scipy.org/doc/numpy/reference/produced/numpy.where.html中,我们可以告诉np在第一个arg到np.where的布尔值之后对要使用的值进行评估。

>>>np.where((MyArray > 5) & (MyArray < 15), MyArray, 999)

array([[999, 999, 999, 999, 999],
   [999,   6,   7,   8,   9],
   [ 10,  11,  12,  13,  14],
   [999, 999, 999, 999, 999]])

话虽如此,“不分配给MyArray问题”的一个很好的例子如下:

>>> MyArray
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
>>> MyArray = MyArray[i]
>>> MyArray
array([ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> MyArray = MyArray[j]
>>> MyArray
array([ 6,  7,  8,  9, 10, 11, 12, 13, 14])

我认为让很多人(包括我自己)绊倒的主要事情是,仅调用MyArray[i]而不将其分配给带有=东西不会使计算机把握小于或大于比较的结果是什么。

maskedarray看起来像具有正确的工具集

import numpy.ma as ma


MyArray=np.arange(20).reshape(4,5)

subma = ma.masked_inside(MyArray, 5, 15)  # lots of ma. logic, arithematic ops

subma.filled(999)

Out[44]: 
array([[  0,   1,   2,   3,   4],
       [999, 999, 999, 999, 999],
       [999, 999, 999, 999, 999],
       [999,  16,  17,  18,  19]])

暂无
暂无

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

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