【问题标题】:Numpy blockwise reduce operationsNumpy 逐块减少操作
【发布时间】:2017-04-05 01:33:37
【问题描述】:

我认为自己是一位经验丰富的 numpy 用户,但我无法找到以下问题的解决方案。假设有以下数组:

# sorted array of times
t = numpy.cumsum(numpy.random.random(size = 100))
#  some values associated with the times
x = numpy.random.random(size=100)
# some indices into the time/data array
indices = numpy.cumsum(numpy.random.randint(low = 1, high=10,size = 20)) 
indices = indices[indices <90] # respect size of 100
if len(indices) % 2: # make number of indices even
    indices = indices[:-1]

# select some starting and end indices
istart = indices[0::2]
iend   = indices[1::2]

我现在想要的是减少值数组x,给定由istartiend 表示的间隔。即

# e.g. use max reduce, I'll probably also need mean and stdv
what_i_want = numpy.array([numpy.max(x[is:ie]) for is,ie in zip(istart,iend)])

我已经用谷歌搜索了很多,但我只能找到通过 stride_tricks 进行的分块操作,它只允许常规块。如果不执行 pyhthon 循环,我无法找到解决方案:-( 在我的实际应用程序中,数组更大,性能也很重要,所以我暂时使用numba.jit

我是否缺少任何能够做到这一点的 numpy 函数?

【问题讨论】:

  • x[0,1) 中是否总是有浮动点数?
  • 没有。 x 通常是一个复杂得多的数组结构。

标签: python arrays numpy indexing reduce


【解决方案1】:

你看过ufunc.reduceat吗?使用np.maximum,您可以执行以下操作:

>>> np.maximum.reduceat(x, indices)

产生沿切片x[indices[i]:indices[i+1]] 的最大值。要得到你想要的 (x[indices[2i]:indices[2i+1]),你可以这样做

>>> np.maximum.reduceat(x, indices)[::2]

如果您不介意x[inidices[2i-1]:indices[2i]] 的额外计算。这会产生以下结果:

>>> numpy.array([numpy.max(x[ib:ie]) for ib,ie in zip(istart,iend)])
array([ 0.60265618,  0.97866485,  0.78869449,  0.79371198,  0.15463711,
        0.72413702,  0.97669218,  0.86605981])

>>> np.maximum.reduceat(x, indices)[::2]
array([ 0.60265618,  0.97866485,  0.78869449,  0.79371198,  0.15463711,
        0.72413702,  0.97669218,  0.86605981])

【讨论】:

  • 太棒了,这正是我想要的。我可以将所有索引保存在一个数组中,然后我不做任何开销计算:) 也许我应该提高我的谷歌搜索技能......
【解决方案2】:

你可以使用numpy.r_
像这样:

what_i_want = np.array([np.max(x[np.r_[ib:ie]]) for ib,ie in zip(istart,iend)])

【讨论】:

    【解决方案3】:

    (非numpy解决方案,使用astropy

    import numpy as np
    from astropy.nddata.utils import block_reduce
    data = np.arange(16).reshape(4, 4)
    block_reduce(data, 2)    
    

    将转换:

    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    

    到:

    array([[10, 18],
           [42, 50]])
    

    有关更多示例,请参阅this

    【讨论】:

      猜你喜欢
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 2017-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多