【问题标题】:Add numpy array elements/slices with same bin assignment添加具有相同 bin 分配的 numpy 数组元素/切片
【发布时间】:2017-09-07 04:45:11
【问题描述】:

我有一些数组A,数组bins 的对应元素包含每一行的bin 分配。我想构造一个数组S,这样

S[0, :] = (A[(bins == 0), :]).sum(axis=0)

使用np.stack 和列表推导很容易做到这一点,但它似乎过于复杂且可读性差。有没有更通用的方法来对具有 bin 分配的数组切片求和(甚至应用一些通用函数)? scipy.stats.binned_statistic 是正确的,但要求 bin 分配和计算函数的值具有相同的形状(因为我使用的是切片,所以情况并非如此)。

例如,如果

A = np.array([[1., 2., 3., 4.],
              [2., 3., 4., 5.],
              [9., 8., 7., 6.],
              [8., 7., 6., 5.]])

bins = np.array([0, 1, 0, 2])

那么它应该会导致

S = np.array([[10., 10., 10., 10.],
              [2.,  3.,  4.,  5. ],
              [8.,  7.,  6.,  5. ]])

【问题讨论】:

    标签: python arrays numpy histogram binning


    【解决方案1】:

    这是matrix-multiplication 使用np.dot 的方法-

    (bins == np.arange(bins.max()+1)[:,None]).dot(A)
    

    示例运行 -

    In [40]: A = np.array([[1., 2., 3., 4.],
        ...:               [2., 3., 4., 5.],
        ...:               [9., 8., 7., 6.],
        ...:               [8., 7., 6., 5.]])
    
    In [41]: bins = np.array([0, 1, 0, 2])
    
    In [42]: (bins == np.arange(bins.max()+1)[:,None]).dot(A)
    Out[42]: 
    array([[ 10.,  10.,  10.,  10.],
           [  2.,   3.,   4.,   5.],
           [  8.,   7.,   6.,   5.]])
    

    性能提升

    创建掩码(bins == np.arange(bins.max()+1)[:,None]) 的更有效方法是这样 -

    mask = np.zeros((bins.max()+1, len(bins)), dtype=bool)
    mask[bins, np.arange(len(bins))] = 1
    

    【讨论】:

    • 这比@Psidom 的解决方案快大约30%,所以接受这个。这对我来说稍微直截了当,但两者都有效。
    【解决方案2】:

    你可以使用np.add.reduceat:

    import numpy as np
    # index to sort the bins
    sort_index = bins.argsort()
    
    # indices where the array needs to be split at
    indices = np.concatenate(([0], np.where(np.diff(bins[sort_index]))[0] + 1))
    
    # sum values where the bins are the same
    np.add.reduceat(A[sort_index], indices, axis=0)
    
    # array([[ 10.,  10.,  10.,  10.],
    #        [  2.,   3.,   4.,   5.],
    #        [  8.,   7.,   6.,   5.]])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 2017-03-06
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多