代码之家  ›  专栏  ›  技术社区  ›  Ian Ashpole

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

  •  2
  • Ian Ashpole  · 技术社区  · 7 年前

    我正在尝试基于子集的子集修改数组的值,但我找不到这样做的方法。我认为这暴露了我对数组索引和子集设置的工作原理以及视图的定义缺乏了解,但我在任何地方都找不到解决方案,所以我希望有人能帮助我。

    示例问题:

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

    那么,第一个例子的错误在哪里呢?

    注:-我知道我的上一个解决方案可以很好地解决这个问题,但我的实际问题必然涉及更多的数据和第二级子集(可能还有第三级…)

    提前感谢,如果这是一件简单的事情,我真的应该能够从文档中为自己解决,那么我深表歉意:我只是无法:(

    4 回复  |  直到 7 年前
        1
  •  2
  •   Vorticity    7 年前

    正如您所说,您的最后一个示例解决了您的问题。你错过的问题是 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 陈述 包含两个数组,中每个维度一个 MyArray公司 . j 包含一个数组,用于中包含的数组的单个维度 . 你想得到 j[0] 中两个数组的元素 .

    希望这是有意义的。如果你有问题,请告诉我。

        2
  •  1
  •   Jacek    7 年前

    尝试创建布尔数组:

    condition_1 = MyArray > 5
    condition_2 = MyArray < 15
    

    然后可以按位使用 & :

    bools = condition1 & condition2
    

    其值如下:

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

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

    MyArray[bools] = 999
    
        3
  •  1
  •   f5r5e5d    7 年前

    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]])
    
        4
  •  1
  •   Dylan    7 年前

    我认为@Vorticity的另一个答案显然是正确的,也是经过深思熟虑的解释,我觉得不同的代码更容易阅读和理解。

    从…起 https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html 我们可以告诉np在第一个参数到np的布尔值之后使用什么值。在何处进行评估。

    >>>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] 没有将其分配给具有 = 不会使计算机保留小于或大于比较的结果。