我正在尝试用python重新实现一个IDL函数:
http://star.pst.qub.ac.uk/idl/REBIN.html
其通过平均将2d阵列的大小缩小整数倍。
例如:
>>> a=np.arange(24).reshape((4,6))
>>> a
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
我想将其调整为(2,3),取相关样本的平均值,预期输出将为:
>>> b = rebin(a, (2, 3))
>>> b
array([[ 3.5, 5.5, 7.5],
[ 15.5, 17.5, 19.5]])
即b[0,0] = np.mean(a[:2,:2]), b[0,1] = np.mean(a[:2,2:4])
等。
我认为我应该重塑为一个4维数组,然后在正确的切片上取平均值,但无法计算出算法。你有什么建议吗?
发布于 2011-11-11 14:53:37
下面是一个基于the answer you've linked的示例(为了清晰起见):
>>> import numpy as np
>>> a = np.arange(24).reshape((4,6))
>>> a
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
>>> a.reshape((2,a.shape[0]//2,3,-1)).mean(axis=3).mean(1)
array([[ 3.5, 5.5, 7.5],
[ 15.5, 17.5, 19.5]])
作为函数:
def rebin(a, shape):
sh = shape[0],a.shape[0]//shape[0],shape[1],a.shape[1]//shape[1]
return a.reshape(sh).mean(-1).mean(1)
发布于 2015-03-14 05:13:36
J.F. Sebastian对2D分箱有一个很好的答案。这是他的"rebin“函数的一个版本,适用于N维:
def bin_ndarray(ndarray, new_shape, operation='sum'):
"""
Bins an ndarray in all axes based on the target shape, by summing or
averaging.
Number of output dimensions must match number of input dimensions and
new axes must divide old ones.
Example
-------
>>> m = np.arange(0,100,1).reshape((10,10))
>>> n = bin_ndarray(m, new_shape=(5,5), operation='sum')
>>> print(n)
[[ 22 30 38 46 54]
[102 110 118 126 134]
[182 190 198 206 214]
[262 270 278 286 294]
[342 350 358 366 374]]
"""
operation = operation.lower()
if not operation in ['sum', 'mean']:
raise ValueError("Operation not supported.")
if ndarray.ndim != len(new_shape):
raise ValueError("Shape mismatch: {} -> {}".format(ndarray.shape,
new_shape))
compression_pairs = [(d, c//d) for d,c in zip(new_shape,
ndarray.shape)]
flattened = [l for p in compression_pairs for l in p]
ndarray = ndarray.reshape(flattened)
for i in range(len(new_shape)):
op = getattr(ndarray, operation)
ndarray = op(-1*(i+1))
return ndarray
发布于 2016-06-20 16:35:02
这里有一种使用矩阵乘法来做你所要求的事情的方法,它不需要用新的数组维数除以旧的数组维数。
首先,我们生成一个行压缩器矩阵和一个列压缩器矩阵(我相信有一种更干净的方法来做这件事,甚至可能只使用numpy操作):
def get_row_compressor(old_dimension, new_dimension):
dim_compressor = np.zeros((new_dimension, old_dimension))
bin_size = float(old_dimension) / new_dimension
next_bin_break = bin_size
which_row = 0
which_column = 0
while which_row < dim_compressor.shape[0] and which_column < dim_compressor.shape[1]:
if round(next_bin_break - which_column, 10) >= 1:
dim_compressor[which_row, which_column] = 1
which_column += 1
elif next_bin_break == which_column:
which_row += 1
next_bin_break += bin_size
else:
partial_credit = next_bin_break - which_column
dim_compressor[which_row, which_column] = partial_credit
which_row += 1
dim_compressor[which_row, which_column] = 1 - partial_credit
which_column += 1
next_bin_break += bin_size
dim_compressor /= bin_size
return dim_compressor
def get_column_compressor(old_dimension, new_dimension):
return get_row_compressor(old_dimension, new_dimension).transpose()
..。例如,get_row_compressor(5, 3)
为您提供了:
[[ 0.6 0.4 0. 0. 0. ]
[ 0. 0.2 0.6 0.2 0. ]
[ 0. 0. 0. 0.4 0.6]]
而get_column_compressor(3, 2)
为您提供了:
[[ 0.66666667 0. ]
[ 0.33333333 0.33333333]
[ 0. 0.66666667]]
然后简单地与行压缩器进行预乘,并与列压缩器进行后乘,以获得压缩矩阵:
def compress_and_average(array, new_shape):
# Note: new shape should be smaller in both dimensions than old shape
return np.mat(get_row_compressor(array.shape[0], new_shape[0])) * \
np.mat(array) * \
np.mat(get_column_compressor(array.shape[1], new_shape[1]))
使用这种技术,
compress_and_average(np.array([[50, 7, 2, 0, 1],
[0, 0, 2, 8, 4],
[4, 1, 1, 0, 0]]), (2, 3))
收益率:
[[ 21.86666667 2.66666667 2.26666667]
[ 1.86666667 1.46666667 1.86666667]]
https://stackoverflow.com/questions/8090229
复制相似问题