Как перебирать строки в DataFrame в Pandas?
Ответ: НЕ *!
Итерация в Pandas - это антипаттерн, и вы должны делать это только тогда, когда вы исчерпали все остальные варианты. Вы не должны использовать какую-либо функцию с iter
в названии для более чем нескольких тысяч строк, иначе вам придется привыкнуть к большому ожиданию.
Вы хотите распечатать DataFrame? Используйте DataFrame.to_string()
а>.
Вы хотите что-то вычислить? В этом случае ищите методы в этом порядке (список изменен с здесь):
- Векторизация
- Подпрограммы Cython
- Составление списков (стандартный
for
цикл)
DataFrame.apply()
a >: i) редукции, которые могут быть выполнены в Cython, ii) итерация в пространстве Python
DataFrame.itertuples()
a > и iteritems()
DataFrame.iterrows()
< / strong>
iterrows
и itertuples
(оба получили много голосов в ответах на этот вопрос) должны использоваться в очень редких случаях, таких как создание объектов строк / наборов имен для последовательной обработки, что на самом деле единственное, для чего эти функции полезны.
Обращение к властям
На странице документации по итерации есть огромное красное поле предупреждения. что говорит:
Итерация по объектам pandas обычно выполняется медленно. Во многих случаях повторение строк вручную не требуется [...].
* На самом деле это немного сложнее, чем нет. df.iterrows()
- правильный ответ на этот вопрос, но векторизация ваших операций - лучший вариант. Я признаю, что есть обстоятельства, при которых невозможно избежать итерации (например, некоторые операции, результат которых зависит от значения, вычисленного для предыдущей строки). Тем не менее, чтобы понять, когда это произойдет, требуется некоторое знакомство с библиотекой. Если вы не уверены, нужно ли вам итеративное решение, скорее всего, нет. PS: Чтобы узнать больше о моем обосновании написания этого ответа, перейдите в самый конец.
Большое количество базовых операций и вычислений векторизованы пандами (либо через NumPy, либо через функции Cythonized). Это включает в себя арифметику, сравнения, (большинство) сокращений, изменение формы (например, поворот), объединения и групповые операции. Просмотрите документацию по Essential Basic Functionality найти подходящий векторизованный метод для вашей задачи.
Если такового не существует, вы можете написать свой собственный, используя custom Расширения Cython.
Понимание списков должно быть вашим следующим портом обращения, если 1) нет доступного векторизованного решения, 2) производительность важна, но недостаточно важна, чтобы пройти через трудности цитонизации вашего кода, и 3) вы пытаетесь выполнить поэлементное преобразование в вашем коде. Существует достаточное количество доказательств, позволяющих предположить, что понимание списка достаточно быстры (а иногда и быстрее) для многих распространенных задач Pandas.
Формула проста,
# Iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# Iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# Iterating over multiple columns - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# Iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]
Если вы можете инкапсулировать свою бизнес-логику в функцию, вы можете использовать понимание списка, которое ее вызывает. Вы можете заставить работать сколь угодно сложные вещи с помощью простоты и скорости необработанного кода Python.
Предостережения
Составление списков предполагает, что с вашими данными легко работать - это означает, что ваши типы данных согласованы и у вас нет NaN, но это не всегда может быть гарантировано.
- Первый из них более очевиден, но при работе с NaN предпочитайте встроенные методы pandas, если они существуют (потому что они имеют гораздо лучшую логику обработки угловых случаев), или убедитесь, что ваша бизнес-логика включает соответствующую логику обработки NaN.
- При работе со смешанными типами данных вы должны перебирать
zip(df['A'], df['B'], ...)
вместо df[['A', 'B']].to_numpy()
, поскольку последний неявно преобразует данные в наиболее распространенный тип. Например, если A является числовым, а B - строкой, to_numpy()
преобразует весь массив в строку, что может быть не тем, что вам нужно. К счастью, zip
объединение столбцов вместе - самый простой способ решения этой проблемы.
* Ваш пробег может отличаться по причинам, указанным в разделе Предостережения выше.
Очевидный пример
Продемонстрируем разницу на простом примере добавления двух столбцов панд A + B
. Это векторизуемый оператор, поэтому будет легко сравнить производительность методов, описанных выше.
для справки. Строка внизу измеряет функцию, написанную в numpandas, стиле Pandas, который сильно смешивается с NumPy, чтобы выжать максимальную производительность. Следует избегать написания кода numpandas, если вы не знаете, что делаете. Придерживайтесь API там, где это возможно (т. Е. Предпочитайте vec
, а не vec_numpy
).
Однако я должен упомянуть, что это не всегда так резко. Иногда ответ на вопрос, какой метод является лучшим для операции, зависит от ваших данных. Мой совет - протестировать разные подходы к своим данным, прежде чем останавливаться на одном.
Дальнейшее чтение
* Строковые методы Pandas векторизованы в том смысле, что они указаны в серии, но работают с каждым элементом. Базовые механизмы по-прежнему являются итеративными, потому что строковые операции по своей природе трудно векторизовать.
Почему я написал этот ответ
Обычная тенденция, которую я замечаю у новых пользователей, - это задавать вопросы в форме «Как я могу перебрать мой df, чтобы выполнить X?». Показан код, который вызывает iterrows()
при выполнении чего-либо внутри цикла for
. Вот почему. Новый пользователь библиотеки, не знакомый с концепцией векторизации, скорее всего, представит код, который решает их проблему, как итерацию по их данным, чтобы что-то сделать. Не зная, как перебирать DataFrame, первое, что они делают, - это Google и в конечном итоге здесь, на этом вопросе. Затем они видят принятый ответ, говорящий им, как это сделать, закрывают глаза и запускают этот код, даже не задавшись вопросом, является ли повторение правильным.
Цель этого ответа - помочь новым пользователям понять, что итерация не обязательно является решением каждой проблемы, и что могут существовать лучшие, более быстрые и идиоматические решения, и что стоит потратить время на их изучение. Я не пытаюсь начать войну итераций против векторизации, но я хочу, чтобы новые пользователи были проинформированы при разработке решений их проблем с этой библиотекой.
person
cs95
schedule
07.04.2019
pandas
- это лучший выбор для чтения файла csv, даже если набор данных небольшой. Просто программировать манипулировать данными с помощью API. - person Forever   schedule 19.11.2019