В прошлом у меня были похожие проблемы с итерацией по фреймам данных - df.iterrows()
на первый взгляд кажется правильным выбором из-за простоты использования, но удобство приходит за цену. Вот полезный блог , в котором описываются методы в пандах для более эффективной итерации.
Результат - не используйте iterrows
. В целом, доступ к строкам кадра данных можно получить, используя индекс в качестве итератора, а затем используя df.loc
или df.iloc
, например:
for i in df.index:
print(df.loc[i, :])
Использование df.apply
Метод apply
позволяет применять пользовательскую функцию ко всем столбцам или строкам кадра данных. Хотя использование здесь может быть несколько не интуитивным, оно является самым быстрым:
import numpy as np
import pandas as pd
def counter(row):
if np.any(row[row > 0]):
return np.sum(row[row > 0])
else:
return 0
N = 100000
df = pd.DataFrame({'A': np.random.randint(0, 2, N),
'B': np.random.randint(0, 2, N),
'C': np.random.randint(0, 2, N),
'D': np.random.randint(0, 2, N)})
df['match-count'] = df.apply(counter, axis=1, raw=True)
Здесь функция будет проверять каждую строку кадра данных (указывается axis=1
); np.any
возвращает True
, если логическое выделение row[row > 0]
не пусто, в этот момент логическое выделение уменьшается на np.sum
, чтобы получить окончательный счет. Мы используем ключевое слово raw
как True
, так что передается необработанный массив numpy
, который следует использовать в операциях сокращения (например, sum) для повышения производительности (см. docs ).
Это займет около 1,2 секунды для запуска на моем компьютере.
Редактировать
Ответ Джио показывает принцип, который я считаю хорошей практикой при использовании панд - если существуют методы (например, sum
, cumsum
), которые могут работать непосредственно с фреймами данных, попытайтесь использовать их, поскольку они всегда будут быстрее.
Там, где подобные методы не существуют, df.apply
может быть полезным, если указать более сложные операции, которые нужно применить - просто совет на будущее!
Редактировать II
В примере с apply выше предполагается, что все столбцы в кадре данных используются в логическом выборе. Если только определенные столбцы имеют числовые значения, которые необходимо использовать для счетчика, используйте предложение Джио в методе counter
:
def counter(row):
selection = row[['in_deeds', 'in_valuation', 'in_property', 'in_sg']] > 0
if np.any(selection):
return np.sum(selection)
else:
return 0