Подтвердить что ты не робот

Группировка массива 2D numpy в среднем

Я пытаюсь группировать массив numpy в меньший размер, беря среднее значение из этих элементов. Например, для создания массива размера 20x20 требуется средний массив 5x5 foreach размером 100x100. Насколько мне нужно обрабатывать огромные данные, это эффективный способ сделать это?

4b9b3361

Ответ 1

Я попробовал это для меньшего массива, поэтому проверьте его на свой:

import numpy as np

nbig = 100
nsmall = 20
big = np.arange(nbig * nbig).reshape([nbig, nbig]) # 100x100

small = big.reshape([nsmall, nbig//nsmall, nsmall, nbig//nsmall]).mean(3).mean(1)

Пример с 6x6 → 3x3:

nbig = 6
nsmall = 3
big = np.arange(36).reshape([6,6])
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],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])

small = big.reshape([nsmall, nbig//nsmall, nsmall, nbig//nsmall]).mean(3).mean(1)

array([[  3.5,   5.5,   7.5],
       [ 15.5,  17.5,  19.5],
       [ 27.5,  29.5,  31.5]])

Ответ 2

Это довольно просто, хотя я чувствую, что это может быть быстрее:

from __future__ import division
import numpy as np
Norig = 100
Ndown = 20
step = Norig//Ndown
assert step == Norig/Ndown # ensure Ndown is an integer factor of Norig
x = np.arange(Norig*Norig).reshape((Norig,Norig)) #for testing
y = np.empty((Ndown,Ndown)) # for testing
for yr,xr in enumerate(np.arange(0,Norig,step)):
    for yc,xc in enumerate(np.arange(0,Norig,step)):
        y[yr,yc] = np.mean(x[xr:xr+step,xc:xc+step])

Вы также можете найти scipy.signal.decimate. Он применяет более сложный фильтр нижних частот, чем простое усреднение, прежде чем сбрасывать данные, хотя вам придется уничтожить одну ось, а затем другую.

Ответ 3

Среднее значение двумерного массива над подмассивами размера NxN:

height, width = data.shape
data = average(split(average(split(data, width // N, axis=1), axis=-1), height // N, axis=1), axis=-1)

Ответ 4

Обратите внимание, что eumiro approach не работает для маскированных массивов, поскольку .mean(3).mean(1) предполагает, что каждое среднее по оси 3 вычислялось из того же числа значений. Если в вашем массиве есть маскированные элементы, это предположение больше не выполняется. В этом случае вам необходимо отслеживать количество значений, используемых для вычисления .mean(3), и заменить .mean(1) на взвешенное среднее значение. Веса - это нормированное число значений, используемых для вычисления .mean(3).

Вот пример:

import numpy as np


def gridbox_mean_masked(data, Nbig, Nsmall):
    # Reshape data
    rshp = data.reshape([Nsmall, Nbig//Nsmall, Nsmall, Nbig//Nsmall])

    # Compute mean along axis 3 and remember the number of values each mean
    # was computed from
    mean3 = rshp.mean(3)
    count3 = rshp.count(3)

    # Compute weighted mean along axis 1
    mean1 = (count3*mean3).sum(1)/count3.sum(1)
    return mean1


# Define test data
big = np.ma.array([[1, 1, 2],
                   [1, 1, 1],
                   [1, 1, 1]])
big.mask = [[0, 0, 0],
            [0, 0, 1],
            [0, 0, 0]]
Nbig = 3
Nsmall = 1

# Compute gridbox mean
print gridbox_mean_masked(big, Nbig, Nsmall)