Вот способ выполнить то, что вы просите, с использованием умножения матриц, для которого не требуется, чтобы новые размеры массива разделяли старые.
Сначала мы сгенерируем матрицу компрессора строки и матрицу компрессора столбца (я уверен, что есть более чистый способ сделать это, может быть, даже используя только отдельные операции):
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]]