Numpy самый быстрый способ применить массив функций к столбцам матрицы - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть массив функций shape (n,) и пустая матрица shape (m, n). Теперь я хочу применить каждую функцию к соответствующему столбцу в матрице, т.е.

matrix[:, i] = funcs[i](matrix[:, i])

Я мог бы сделать это с помощью цикла for (см. Пример ниже), но использование циклов for обычно не рекомендуется в numpy. Мой вопрос: какой самый быстрый (и желательно самый элегантный) способ сделать это?

Рабочий пример

import numpy as np

# Example of functions to apply to each row
funcs  = np.array([np.vectorize(lambda x: x+1),
                   np.vectorize(lambda x: x-2),
                   np.vectorize(lambda x: x+3)])
# Initialise dummy matrix
matrix = np.random.rand(50, 3)

# Apply each function to each column
for i in range(funcs.shape[0]):
    matrix[:, i] = funcs[i](matrix[:, i])

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Здесь эффективен цикл, так как работа в цикле тяжелая.

Читаемое решение просто:

np.vectorize(apply)(funcs,matrix)
0 голосов
/ 04 сентября 2018

Для массива, который имеет много строк и несколько столбцов, простая итерация столбца должна быть эффективной по времени:

In [783]: funcs = [lambda x: x+1, lambda x: x+2, lambda x: x+3]
In [784]: arr = np.arange(12).reshape(4,3)
In [785]: for i in range(3):
     ...:     arr[:,i] = funcs[i](arr[:,i])
     ...:     
In [786]: arr
Out[786]: 
array([[ 1,  3,  5],
       [ 4,  6,  8],
       [ 7,  9, 11],
       [10, 12, 14]])

Если функции работают с входными данными 1d-массива, нет необходимости в np.vectorize (np.vectorize, как правило, медленнее, чем обычная итерация в любом случае.) Также для такой итерации нет необходимости заключать список функций в массив. В списках быстрее выполнять итерации.

Изменение индексированной итерации:

In [787]: for f, col in zip(funcs, arr.T):
     ...:     col[:] = f(col)
     ...:     
In [788]: arr
Out[788]: 
array([[ 2,  5,  8],
       [ 5,  8, 11],
       [ 8, 11, 14],
       [11, 14, 17]])

Здесь я использую arr.T, поэтому итерация выполняется по столбцам arr, а не по строкам.

Общее замечание: несколько итераций для сложной задачи - это очень хороший стиль numpy. Многие итерации простых задач выполняются медленно, и, по возможности, их следует выполнять в скомпилированном коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...