Эффективная обработка строк DataFrame с помощью функции Python?

Во многих местах нашего Pandas -using кода у нас есть функция Python process(row). Эта функция используется над DataFrame.iterrows(), беря каждую row и обрабатывая некоторую обработку и возвращая значение, которое мы окончательно собираем в новый Series.

Я понимаю, что эта схема использования обходит большинство преимуществ производительности стека numpy/ Pandas.

  • Что было бы лучшим способом сделать эту модель использования эффективной? насколько возможно?
  • Можем ли мы это сделать, не переписывая большую часть нашего кода?

Еще один аспект этого вопроса: можно ли преобразовать все такие функции в числовое представление? Мне нужно много узнать о стеке numpy/scipy/ Pandas, но кажется, что для действительно произвольной логики иногда вам может понадобиться просто медленная чистая архитектура Python, такая как выше. Это тот случай?

Ответ 1

Вы должны применить свою функцию вдоль оси = 1. Функция получит строку в качестве аргумента, и все, что она вернет, будет собрано в новый объект серии

df.apply(you_function, axis=1)

Пример:

>>> df = pd.DataFrame({'a': np.arange(3),
                       'b': np.random.rand(3)})
>>> df
   a         b
0  0  0.880075
1  1  0.143038
2  2  0.795188
>>> def func(row):
        return row['a'] + row['b']
>>> df.apply(func, axis=1)
0    0.880075
1    1.143038
2    2.795188
dtype: float64

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

Некоторая операция может быть преобразована в ориентированные на столбцы (одна в моем примере может быть легко преобразована только в df['a'] + df['b']), но другие не могут. Особенно, если у вас много ветвлений, особых случаев или другой логики, которые должны выполняться в вашей строке. В этом случае, если apply слишком медленный для вас, я бы предложил "Cython-izing" ваш код. Cython отлично играет с NumPy C api и даст вам максимальную скорость, которую вы можете достичь.

Или вы можете попробовать numba.:)