2013-03-28 5 views
1

Я реализую подкласс ndarray numpy и мне нужно изменить __getitem__ для извлечения элементов из сплющенного представления массива. Проблема в том, что __getitem__ может быть вызван с целым индексом или многомерным срезом.Как сгладить ломтик numpy?

Кто-нибудь знает, как преобразовать многомерный срез в список индексов (или одномерный срез) на сплющенном массиве?

ответ

2

Это не может быть возможно преобразовать многомерный ломтик плоского среза, например .:

>>> a = np.arange(16).reshape(4, 4) 
>>> a 
array([[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11], 
     [12, 13, 14, 15]]) 
>>> a[::3, 1::2] 
array([[ 1, 3], 
     [13, 15]]) 

И вы не можете получить доступ к подмассиву [ 1, 3, 13, 15] с start:stop:step нотации. Но вы можете создать список плоских индексов из многомерных единиц, делать что-то вроде следующего:

>>> row_idx = np.arange(4)[::3] 
>>> col_idx = np.arange(4)[1::2] 
>>> row_idx = np.repeat(row_idx, 2) 
>>> col_idx = np.tile(col_idx, 2) 
>>> np.ravel_multi_index((row_idx, col_idx), dims=(4,4)) 
array([ 1, 3, 13, 15], dtype=int64) 

В более общем случае, когда у вас есть массив индексов для каждого измерения, необходимо Buld декартова произведение всех индексных массивов, поэтому itertools.product, вероятно, путь. Например:

>>> indices = [np.array([0, 4, 8]), np.array([1,7]), np.array([3, 5, 9])] 
>>> indices = zip(*itertools.product(*indices)) 
>>> indices 
[(0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8), 
(1, 1, 1, 7, 7, 7, 1, 1, 1, 7, 7, 7, 1, 1, 1, 7, 7, 7), 
(3, 5, 9, 3, 5, 9, 3, 5, 9, 3, 5, 9, 3, 5, 9, 3, 5, 9)] 
>>> np.ravel_multi_index(indices, dims=(10, 11, 12)) 
array([ 15, 17, 21, 87, 89, 93, 543, 545, 549, 615, 617, 
     621, 1071, 1073, 1077, 1143, 1145, 1149], dtype=int64) 
+0

Очень интересно, обобщать это, вы должны знать форму вашей матрицы (легко) и сколько шагов походку поместится в вашей матрице (для повторения и плиточные функций). Вторая предпосылка не так проста, но должна быть выполнимой. – fccoelho

+0

@fccoelho Это не так сложно, я думаю, что 'row_idx = np.repeat (row_idx, len (col_idx))' и 'col_idx = np.tile (col_idx, len (row_idx))' - это то, что вам нужно, чтобы обобщить выше подхода. – Jaime

+0

Спасибо, Хайме. Ты прав. – fccoelho

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