Numpy ребинирует двумерный массив

Я ищу быструю формулировку для числового бинирования массива 2D numpy. Под биннингом я подразумеваю вычисление средних значений подматрицы или кумулятивных значений. Например x = numpy.arange(16).reshape(4, 4) был бы разделен на 4 подматрицы 2x2 каждая и дал бы numpy.array([[2.5,4.5],[10.5,12.5]]), где 2.5=numpy. среднее ([0,1,4,5]) и т.д...

Как эффективно выполнить такую ​​операцию... Я понятия не имею, как это сделать...

Большое спасибо...


person user1187727    schedule 17.02.2013    source источник
comment
Гарантируется ли точное соответствие подматриц? у вас есть numpy 1.7. доступны (это просто аккуратно, не обязательно)?   -  person seberg    schedule 17.02.2013
comment
У меня numpy 1.8dev, но моя работа становится старше...   -  person user1187727    schedule 17.02.2013


Ответы (3)


Вы можете использовать представление вашего массива в более высоком измерении и взять среднее значение по дополнительным измерениям:

In [12]: a = np.arange(36).reshape(6, 6)

In [13]: a
Out[13]: 
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]])

In [14]: a_view = a.reshape(3, 2, 3, 2)

In [15]: a_view.mean(axis=3).mean(axis=1)
Out[15]: 
array([[  3.5,   5.5,   7.5],
       [ 15.5,  17.5,  19.5],
       [ 27.5,  29.5,  31.5]])

В общем, если вам нужны ячейки формы (a, b) для массива (rows, cols), ваше изменение формы должно быть .reshape(rows // a, a, cols // b, b). Также обратите внимание, что порядок .mean важен, например. a_view.mean(axis=1).mean(axis=3) вызовет ошибку, потому что a_view.mean(axis=1) имеет только три измерения, хотя a_view.mean(axis=1).mean(axis=2) будет работать нормально, но это усложняет понимание того, что происходит.

Как есть, приведенный выше код работает только в том случае, если вы можете разместить целое число ячеек внутри вашего массива, то есть если a делит rows и b делит cols. Есть способы справиться с другими случаями, но тогда вам придется определить поведение, которое вы хотите.

person Jaime    schedule 17.02.2013
comment
На нумпи 1.7. вы можете раздавить его вместе в .mean(axis=(1,3))! - person seberg; 17.02.2013
comment
Я не знал, что такое изменение формы возможно, здорово! К сожалению, среднее значение зависит от того, как получить среднее значение для напр. подматрица 2,2 в вашем примере (я имею в виду угол 0,1,6,7 и т.д...)? - person user1187727; 17.02.2013
comment
@user1187727 user1187727 Я не думаю, что понимаю ваш вопрос, но среднее значение [[0, 1], [6, 7]] равно элементу [0, 0] из a_view.mean(axis=3).mean(axis=1). - person Jaime; 17.02.2013
comment
Я думаю, @user1187727 был сбит с толку тем фактом, что измененный массив (с reshape(3, 2, 3, 2)) не является массивом подматриц 2x2, хотя результат в любом случае правильный. - person shaman.sir; 19.07.2017

См. поваренную книгу SciPy по повторному связыванию, в которой есть этот фрагмент:

def rebin(a, *args):
    '''rebin ndarray data into a smaller ndarray of the same rank whose dimensions
    are factors of the original dimensions. eg. An array with 6 columns and 4 rows
    can be reduced to have 6,3,2 or 1 columns and 4,2 or 1 rows.
    example usages:
    >>> a=rand(6,4); b=rebin(a,3,2)
    >>> a=rand(6); b=rebin(a,2)
    '''
    shape = a.shape
    lenShape = len(shape)
    factor = asarray(shape)/asarray(args)
    evList = ['a.reshape('] + \
             ['args[%d],factor[%d],'%(i,i) for i in range(lenShape)] + \
             [')'] + ['.sum(%d)'%(i+1) for i in range(lenShape)] + \
             ['/factor[%d]'%i for i in range(lenShape)]
    print ''.join(evList)
    return eval(''.join(evList))
person Paul Price    schedule 21.02.2014

Я предполагаю, что вы только хотите знать, как в целом построить функцию, которая хорошо работает и что-то делает с массивами, как numpy.reshape в вашем примере. Поэтому, если производительность действительно имеет значение, и вы уже используете numpy, вы можете написать для этого свой собственный код C, как это делает numpy. Например, реализация arange полностью на C. Почти все, что имеет значение с точки зрения производительности, реализовано на C.

Однако перед этим вы должны попробовать реализовать код на python и посмотреть, достаточно ли хороша производительность. Попробуйте сделать код Python максимально эффективным. Если он по-прежнему не соответствует вашим потребностям в производительности, идите по пути C.

Вы можете прочитать об этом в документах.

person nemo    schedule 17.02.2013