2013-09-17 2 views
5

с учетом np.array формы (n_days, n_lat, n_lon), я бы хотел вычислить гистограмму с фиксированными ячейками для каждой ячейки lat-lon (т.е. распределение ежедневных значений).Гистограмма Numpy на многомерном массиве

Простое решение этой проблемы заключается в петле над клетками и вызывать np.histogram для каждой ячейки ::

bins = np.linspace(0, 1.0, 10) 
B = np.rand(n_days, n_lat, n_lon) 
H = np.zeros((n_bins, n_lat, n_lon), dtype=np.int32) 
for lat in range(n_lat): 
    for lon in range(n_lon): 
     H[:, lat, lon] = np.histogram(A[:, lat, lon], bins=bins)[0] 
# note: code not tested 

, но это довольно медленно. Существует ли более эффективное решение, не связанное с циклом?

Я посмотрел в np.searchsorted, чтобы получить бен индексы для каждого значения в B, а затем использовать фантазии индексации обновить H ::

bin_indices = bins.searchsorted(B) 
H[bin_indices.ravel(), idx[0], idx[1]] += 1 # where idx is a index grid given by np.indices 
# note: code not tested 

, но это не работает, потому что в месте добавить оператор (+ =), похоже, не поддерживает несколько обновлений одной и той же ячейки.

ТНХ, Питер

+0

похоже, что https://github.com/numpy/numpy/pull/2821 обратился к причудливой индексации и проблеме на месте. Причина, по которой numpy не разрешает множественные обновления, состоит в том, что '' a [idx] + = 1'' не будет таким же, как '' a [idx] = a [idx] + 1''. –

+0

Используйте ['np.histogram2d'] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram2d.html) с аргументом ключевого слова' weightights'. – Jaime

+0

@Jaime, как бы использовать «вес»? Я не хочу делать 2d гистограмму. –

ответ

3

Вы можете использовать numpy.apply_along_axis устранить петлю.

hist, bin_edges = apply_along_axis(lambda x: histogram(x, bins=bins), 0, B) 
+0

это выглядит интересно, действительно - thx –

+0

@PeterPrettenhofer только что зафиксировал опечатку. У лямбды были буквы. Надеюсь, что это работает для вас. –

0

Может быть, это работает ?:

import numpy as np 
n_days=31 
n_lat=10 
n_lon=10 
n_bins=10 
bins = np.linspace(0, 1.0, n_bins) 
B = np.random.rand(n_days, n_lat, n_lon) 


# flatten to 1D 
C=np.reshape(B,n_days*n_lat*n_lon) 
# use digitize to get the index of the bin to which the numbers belong 
D=np.digitize(C,bins)-1 
# reshape the results back to the original shape 
result=np.reshape(D,(n_days, n_lat, n_lon)) 
+0

это дает мне в основном то же самое, что '' bins.searchsorted (B) '', массив формы '' (n_days, n_lat, n_lon) ', но сложной частью является его преобразование в' '(n_bins, n_lat , n_lon) ''. –

Смежные вопросы