Numpy 逐块减少操作
Numpy blockwise reduce operations
我认为自己是一位经验丰富的 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]
我现在想要的是在给定 istart
和 iend
表示的间隔的情况下减少值数组 x
。即
# 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
进行的分块操作,它只允许常规块。如果不执行 python 循环,我无法找到解决方案:-(
在我的实际应用程序中,数组要大得多,性能也很重要,所以我暂时使用 numba.jit
。
我是否缺少任何能够做到这一点的 numpy 函数?
你可以使用numpy.r_
像这样:
what_i_want = np.array([np.max(x[np.r_[ib:ie]]) for ib,ie in zip(istart,iend)])
你看过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])
(非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。
我认为自己是一位经验丰富的 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]
我现在想要的是在给定 istart
和 iend
表示的间隔的情况下减少值数组 x
。即
# 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
进行的分块操作,它只允许常规块。如果不执行 python 循环,我无法找到解决方案:-(
在我的实际应用程序中,数组要大得多,性能也很重要,所以我暂时使用 numba.jit
。
我是否缺少任何能够做到这一点的 numpy 函数?
你可以使用numpy.r_
像这样:
what_i_want = np.array([np.max(x[np.r_[ib:ie]]) for ib,ie in zip(istart,iend)])
你看过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])
(非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。