Каковы эффективные способы зацикливания векторов вдоль указанной оси в numpy ndarray?

Я обрабатываю данные, зацикливаясь на векторах вдоль оси (может быть любой оси) numpy ndarray (может иметь любые размеры).

Я не работал с массивом напрямую, потому что данные не идеальны. Требуется контроль качества каждого вектора. Если это не хорошо, вектор будет заполнен нулями (или нан) и не будет иметь реальной обработки.

я нашелэтот вопрос похоже, но моя проблема гораздо сложнее, потому что

ndim произвольно.

Для трехмерного массива я могу взять векторыaxis 1 как это

 x = np.arange(24).reshape(2,3,4)
 for i in range(x.shape[0]):
     for k in range(x.shape[2]):
         process(x[i,:,k])

но еслиndim и взятыйaxis не фиксируются, как взять векторы?

Ось взятия векторов произвольна.

Один из возможных способов, который я рассматриваю,

 y = x.swapaxes(ax,-1)
 # loop over vectors along last axis
 for i in np.ndindex(y.shape[:-1]):
     process(y[i+(slice(None),)])
 # then swap back
 z = y.swapaxes(ax,-1)

Но я сомневаюсь в эффективности этого метода.

 Vince W.05 июл. 2016 г., 19:04
Можете ли вы рассказать немного больше о том, почему вы хотите обрабатывать данные в линейных векторах, а не в виде целого массива?
 Vince W.06 июл. 2016 г., 15:09
Мне нравится ответ hpaulj. Если скорость абсолютно критична, вам следует рассмотреть возможность создания скомпилированных функций numba для обработки множества форм, которые вы будете выполнять, а затем проанализировать входные данные, чтобы определить, к какой функции numba передать ее.
 M.T05 июл. 2016 г., 18:55
в зависимости от функцииprocess и количество циклов, возможно, стоит использоватьNumba«sjit декоратор
 Divakar05 июл. 2016 г., 17:44
Наиболее эффективным способом было быне итерация / цикл, который модифицирует (если еще не применяется)process обрабатывать все кусочки за один раз. Итак, вы работаете с конкретнымprocess FUNC? Если нет, посмотрите вnp.vectorize Я думаю.
 Lee05 июл. 2016 г., 17:47
Я не работал с массивом напрямую, потому что массив данных не идеален. Требуется контроль качества каждого вектора. Если не хорошо, вектор будет заполнен нулями (или нан).
 hpaulj06 июл. 2016 г., 01:13
Вам не нужноswapaxes в последнем примере - см. мои правки.
 Lee06 июл. 2016 г., 13:35
@VinceWest Для каждого вектора мне нужно проверить достоверность временных рядов, заменив неправильные значения (например, inf, nan) и сбои нулями, и посчитав ненулевые значения (значения abs меньше 1e-13, считающиеся нулями) , Векторы с ненулевыми значениями ниже порогового значения будут отбрасываться иzeros или жеnans будет заполнен вектором в результирующем массиве. Для хороших векторов применяются некоторые базовые обработки сигналов, такие как детрендовая, полосовая фильтрация. Другие операции могут бытьrfftоконные расчетыrange, std, mean, median ...

Ответы на вопрос(2)

Вы рассматривалиnumpy.nditer?

Смотрите такжеПеребор массивов.

РЕДАКТИРОВАТЬ: может быть, другое решение будет просто использовать:

flattenravelflat 1D итератор

Таким образом, вы можете перебирать 1D-подобный любой начальный dim массива, а затемreshape массив в исходную форму.

 Lee05 июл. 2016 г., 18:06
На самом деле, встроенные функции NumPy, какmean, sum, fft, ..., всегда может иметь дело с ndarray независимо от того, чтоndim а такжеaxis, Но я не понял, как они это делают, хотя я взглянул на исходные коды.
 Lee05 июл. 2016 г., 18:03
Я получил похожую идею, используяnp.ndindex отstackoverflow.com/questions/29493183/...  но также упомянул, чтоnditer даже медленнее, чем для цикла.
 Tttt122805 июл. 2016 г., 18:27
Я думаю, что они на самом деле обернуть предварительно скомпилированный код C (в котором циклы действительно происходят), смотритеЧто такое NumPy, Рассматривали ли вы возможность проверить ваши данные, используя некоторые из векторизованных функций numpy (см., Например,docs.scipy.org/doc/numpy/reference/routines.logic.html) и клочковатыйиндексирование какой действительно мощный? Если вам определенно нужно зацикливаться, возможно, вам следует подуматьCython и использовать его для написания циклического кода C, изначально вызываемого из Python
Решение Вопроса

Лучший способ проверить эффективность - провести временные тесты на реалистичных примерах. Но%timeit (ipython) тесты на игрушечных примерах - это начало.

Основываясь на опыте ответов на подобные вопросы «если вам нужно повторить», разница во времени невелика.np.frompyfunc имеет скромное преимущество в скорости - но егоpyfunc принимает скаляры, а не массивы или ломтики. (np.vectorize является более приятным API для этой функции и немного медленнее).

Но здесь вы хотите передать 1d срез массива в вашу функцию, итерируя по всем остальным измерениям. Я не думаю, что есть большая разница в альтернативных методах итерации.

Действия какswapaxis, transpose а такжеravel быстрые, часто просто создают новый вид с другой формой и шагами.

np.ndindex использованияnp.nditer (с мультииндексом flat) для итерации по диапазону измерений.nditer быстр в использовании в коде на C, но ничего особенного, когда используется в коде Python.

np.apply_along_axis создает(i,j,:,k) индексация кортежа и пошаговые переменные. Это хороший общий подход, но он не делает ничего особенного, чтобы ускорить процесс.itertools.product это еще один способ генерации индексов.

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

def foo(x):
   return x

===================

Вам не нужноswapaxes использоватьndindex; Вы можете использовать его для итерации по любой комбинации осей.

Например, создайте трехмерный массив и суммируйте по среднему измерению:

In [495]: x=np.arange(2*3*4).reshape(2,3,4)

In [496]: N=np.ndindex(2,4)

In [497]: [x[i,:,k].sum() for i,k in N]
Out[497]: [12, 15, 18, 21, 48, 51, 54, 57]

In [498]: x.sum(1)
Out[498]: 
array([[12, 15, 18, 21],
       [48, 51, 54, 57]])

Я не думаю, что это имеет значение в скорости; код просто проще

===================

Еще один возможный инструментnp.ma, замаскированные массивы. С их помощью вы помечаете отдельные элементы как маскированные (потому что ониnan или же0). У него есть код, который оценивает такие вещи, какsum, mean, product таким образом, чтобы замаскированные значения не повредили решение.

3-й массив снова:

In [517]: x=np.arange(2*3*4).reshape(2,3,4)

добавить некоторые плохие значения:

In [518]: x[1,1,2]=99    
In [519]: x[0,0,:]=99

эти значения портят нормальноеsum:

In [520]: x.sum(axis=1)
Out[520]: 
array([[111, 113, 115, 117],
       [ 48,  51, 135,  57]])

но если мы их маскируем, они «отфильтровываются» из решения (в этом случае они временно устанавливаются в 0)

In [521]: xm=np.ma.masked_greater(x,50)

In [522]: xm
Out[522]: 
masked_array(data =
 [[[-- -- -- --]
  [4 5 6 7]
  [8 9 10 11]]

 [[12 13 14 15]
  [16 17 -- 19]
  [20 21 22 23]]],
             mask =
 [[[ True  True  True  True]
 ...
  [False False False False]]],
       fill_value = 999999)

In [523]: xm.sum(1)
Out[523]: 
masked_array(data =
 [[12 14 16 18]
 [48 51 36 57]],
 ...)

Ваш ответ на вопрос