【问题标题】:Numpy array loss of dimension when masking屏蔽时的 Numpy 数组维度丢失
【发布时间】:2015-05-16 18:10:34
【问题描述】:

我想选择数组的某些元素并根据这些值执行加权平均计算。但是,使用过滤条件会破坏数组的原始结构。形状为(2, 2, 3, 2)arr 变成了一维数组。这对我没有用,因为并非所有这些元素都需要稍后相互组合(但它们的子数组)。如何避免这种扁平化?

>>> arr = np.asarray([ [[[1, 11], [2, 22], [3, 33]], [[4, 44], [5, 55], [6, 66]]], [ [[7, 77], [8, 88], [9, 99]], [[0, 32], [1, 33], [2, 34] ]] ])
>>> arr
array([[[[ 1, 11],
         [ 2, 22],
         [ 3, 33]],

        [[ 4, 44],
         [ 5, 55],
         [ 6, 66]]],


       [[[ 7, 77],
         [ 8, 88],
         [ 9, 99]],

        [[ 0, 32],
         [ 1, 33],
         [ 2, 34]]]])
>>> arr.shape
(2, 2, 3, 2)
>>> arr[arr>3]
array([11, 22, 33,  4, 44,  5, 55,  6, 66,  7, 77,  8, 88,  9, 99, 32, 33,
       34])
>>> arr[arr>3].shape
(18,)

【问题讨论】:

  • 详细说明您需要对这些值进行的计算。你将如何使用arr 结构?

标签: python arrays numpy


【解决方案1】:

很明显,您需要 2 做的是首先重新调整数组的形状,然后像这样进行转换:

maschked_data = data[:,0][np.zeros(np.reshape(data, -1), np.reshape(data, -1).shape[0])[:,0].shape[0]]

数据[:,0]

【讨论】:

    【解决方案2】:

    另一方面,如果您需要将最小值替换为小于您检查的值的值(在您的示例中为3),那么您可以使用numpy.clip()ndarray.clip()

    In [27]: np.clip(arr, 3, np.max(arr))
    Out[27]: 
    array([[[[ 3, 11],
             [ 3, 22],
             [ 3, 33]],
    
            [[ 4, 44],
             [ 5, 55],
             [ 6, 66]]],
    
    
           [[[ 7, 77],
             [ 8, 88],
             [ 9, 99]],
    
            [[ 3, 32],
             [ 3, 33],
             [ 3, 34]]]])
    

    【讨论】:

      【解决方案3】:

      您可以考虑使用np.ma.masked_array 来表示满足您条件的元素子集:

      import numpy as np
      
      arr = np.asarray([[[[1, 11], [2, 22], [3, 33]],
                         [[4, 44], [5, 55], [6, 66]]],
                        [[[7, 77], [8, 88], [9, 99]],
                         [[0, 32], [1, 33], [2, 34]]]])
      
      masked_arr = np.ma.masked_less(arr, 3)
      
      print(masked_arr)
      # [[[[-- 11]
      #    [-- 22]
      #    [3 33]]
      
      #   [[4 44]
      #    [5 55]
      #    [6 66]]]
      
      
      #  [[[7 77]
      #    [8 88]
      #    [9 99]]
      
      #   [[-- 32]
      #    [-- 33]
      #    [-- 34]]]]
      

      如您所见,掩码数组保留其原始尺寸。您可以分别通过.data.mask 属性访问基础数据和掩码。大多数 numpy 函数不会考虑掩码值,例如:

      # mean of whole array
      print(arr.mean())
      # 26.75
      
      # mean of non-masked elements only
      print(masked_arr.mean())
      # 33.4736842105
      

      对掩码数组和非掩码数组进行元素操作的结果也将保留掩码的值:

      masked_arrsum = masked_arr + np.random.randn(*arr.shape)
      
      print(masked_arrsum)
      # [[[[-- 11.359989067421582]
      #    [-- 23.249092437269162]
      #    [3.326111354088174 32.679132708120726]]
      
      #   [[4.289134334263137 43.38559221094378]
      #    [6.028063054523145 53.5043991898567]
      #    [7.44695154979811 65.56890530368757]]]
      
      
      #  [[[8.45692625294376 77.36860675985407]
      #    [5.915835159196378 87.28574554110307]
      #    [8.251106168209688 98.7621940026713]]
      
      #   [[-- 33.24398289945855]
      #    [-- 33.411941757624284]
      #    [-- 34.964817895873715]]]]
      

      总和仅在 masked_arr 的非屏蔽值上计算 - 您可以通过查看 masked_sum.data 看到这一点:

      print(masked_sum.data)
      # [[[[  1.          11.35998907]
      #    [  2.          23.24909244]
      #    [  3.32611135  32.67913271]]
      
      #   [[  4.28913433  43.38559221]
      #    [  6.02806305  53.50439919]
      #    [  7.44695155  65.5689053 ]]]
      
      
      #  [[[  8.45692625  77.36860676]
      #    [  5.91583516  87.28574554]
      #    [  8.25110617  98.762194  ]]
      
      #   [[  0.          33.2439829 ]
      #    [  1.          33.41194176]
      #    [  2.          34.9648179 ]]]]
      

      【讨论】:

      • 有趣。我认为arr[arr<3] 会隐式创建一个掩码数组 - 学到了一些新东西 (+1)。
      • 请记住,arr < 3 只是一个布尔数组,使用布尔数组进行索引将始终只返回 arr 中的那些元素,其中布尔索引为 True。出于好奇,你最后为什么选择np.where?在这三个答案中,这似乎是实现您所追求的最不直接的方法。
      • 我在你和np.where 之间辗转反侧。我选择了它,因为它符合单行代码的目的。这似乎是最合适的。都是很好的答案...
      【解决方案4】:

      arr>3

      In [71]: arr>3
      Out[71]: 
      array([[[[False,  True],
               [False,  True],
               [False,  True]],
      
              [[ True,  True],
               [ True,  True],
               [ True,  True]]],
      
      
             [[[ True,  True],
               [ True,  True],
               [ True,  True]],
      
              [[False,  True],
               [False,  True],
               [False,  True]]]], dtype=bool)
      

      arr[arr>3] 选择掩码为True 的元素。您希望该选择具有什么样的结构或形状?扁平是唯一有意义的东西,不是吗? arr 本身没有改变。

      您可以将不适合掩码的术语归零,

      In [84]: arr1=arr.copy()
      In [85]: arr1[arr<=3]=0
      In [86]: arr1
      Out[86]: 
      array([[[[ 0, 11],
               [ 0, 22],
               [ 0, 33]],
      
              [[ 4, 44],
               [ 5, 55],
               [ 6, 66]]],
      
      
             [[[ 7, 77],
               [ 8, 88],
               [ 9, 99]],
      
              [[ 0, 32],
               [ 0, 33],
               [ 0, 34]]]])
      

      现在您可以对各个维度进行重量总和或平均值。

      np.nonzero(或np.where)也可能有用,为您提供所选术语的索引:

      In [88]: np.nonzero(arr>3)
      Out[88]: 
      (array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
       array([0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1]),
       array([0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2]),
       array([1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1]))
      

      【讨论】:

        【解决方案5】:

        结帐numpy.where

        http://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html

        为了保持相同的维度,您需要一个填充值。在下面的示例中,我使用 0,但您也可以使用 np.nan

        np.where(arr>3, arr, 0)
        

        返回

        array([[[[ 0, 11],
                 [ 0, 22],
                 [ 0, 33]],
        
                [[ 4, 44],
                 [ 5, 55],
                 [ 6, 66]]],
        
        
               [[[ 7, 77],
                 [ 8, 88],
                 [ 9, 99]],
        
                [[ 0, 32],
                 [ 0, 33],
                 [ 0, 34]]]])
        

        【讨论】:

        • 这就是我要找的。​​span>
        • 感谢提醒where 使用第二个和第三个参数;我总是忘记他们的(实际)用途。
        猜你喜欢
        • 2015-07-29
        • 1970-01-01
        • 1970-01-01
        • 2016-11-06
        • 1970-01-01
        • 2017-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多