Как выполнить итерацию по строкам в DataFrame в Pandas

python pandas rows dataframe


У меня есть DataFrame от панд:

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df

Output:

   c1   c2
0  10  100
1  11  110
2  12  120

Теперь я хочу провести итерацию по рядам этого кадра.Для каждой строки я хочу иметь доступ к ее элементам (значениям в ячейках)по имени столбцов.Например:

for row in df.rows:
   print row['c1'], row['c2']

Это возможно в пандах?

Я нашел этот похожий вопрос . Но это не дает мне ответ, который мне нужен. Например, там предлагается использовать:

for date, row in df.T.iteritems():

or

for row in df.iterrows():

Но я не понимаю, что такое row объект и как я могу с ним работать.





Answer 1 waitingkuo


DataFrame.iterrows - это генератор, который выдает как индекс, так и строку

import pandas as pd
import numpy as np

df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])

for index, row in df.iterrows():
    print(row['c1'], row['c2'])

Output: 
   10 100
   11 110
   12 120



Answer 2 viddik13


Сначала подумайте, действительно ли вам нужно перебирать строки в DataFrame. Смотрите этот ответ для альтернатив.

Если вам все еще нужно перебирать строки, вы можете использовать методы ниже. Обратите внимание на некоторые важные предостережения, которые не упоминаются ни в одном из других ответов.

itertuples() должен быть быстрее, чем iterrows()

Но имейте в виду,согласно документам (панды 0.24.2 на данный момент):

  • iterrows: dtype может не совпадать от строки к строке

    Поскольку iterrows возвращает Series для каждой строки, он не сохраняет dtypes по строкам (dtypes сохраняются по столбцам для DataFrames). Чтобы сохранить dtypes при выполнении итераций по строкам, лучше использовать itertuples (), которая возвращает именованные кортежи значений и, как правило, намного быстрее, чем iterrows ()

  • итерроуты:Не изменять строки

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

    Вместо этого используйте DataFrame.apply () :

    new_df = df.apply(lambda x: x * 2)
  • itertuples:

    Имена столбцов будут переименованы в позиционные имена, если они являются недопустимыми идентификаторами Python, повторяются или начинаются с подчеркивания. При большом количестве столбцов (> 255) возвращаются обычные кортежи.

Смотрите pandas docs на итерации для более подробной информации.




Answer 3 cs95


Как выполнить итерацию по строкам в DataFrame в Pandas?

Ответ: НЕ * !

Итерации в пандах - это анти-паттерн, и вы должны делать это только тогда, когда исчерпали все остальные опции. Вы не должны использовать какую-либо функцию с « iter » в названии более нескольких тысяч строк, иначе вам придется привыкнуть к большим ожиданиям.

Хотите распечатать DataFrame? Используйте DataFrame.to_string() .

Вы хотите что-то вычислить? В этом случае ищите методы в следующем порядке (список изменен здесь ):

  1. Vectorization
  2. режимы Сайфона
  3. Список Пониманий (ваниль for петли)
  4. DataFrame.apply() : i) сокращения, которые могут быть выполнены в cython, ii) итерации в пространстве python
  5. DataFrame.itertuples() и iteritems()
  6. DataFrame.iterrows()

iterrows и itertuples (оба получают много голосов в ответах на этот вопрос) должны использоваться в очень редких случаях, таких как генерация объектов строк / именных имен для последовательной обработки, что на самом деле является единственной вещью, для которой эти функции полезны.

Обращение к власти
Страница документации по итерации имеет огромное красное окно с предупреждением:

Проникновение сквозь предметы панд,как правило,медленное.Во многих случаях итерация вручную по строкам не нужна [...].

* Это на самом деле немного сложнее, чем "нет". df.iterrows() - правильный ответ на этот вопрос, но лучше использовать векторизацию ваших операций. Я признаю, что существуют обстоятельства, при которых нельзя избежать итерации (например, некоторые операции, в которых результат зависит от значения, вычисленного для предыдущей строки). Однако для того, чтобы узнать, когда нужно, нужно некоторое знакомство с библиотекой. Если вы не уверены, нужно ли вам итеративное решение, скорее всего, нет. PS: Чтобы узнать больше о моем обосновании написания этого ответа, перейдите к самому низу.


Быстрее, чем зацикливание: векторизация , Cython

Большое количество базовых операций и вычислений "векторизовано" пандами (либо через NumPy, либо через функции Cythonized). Это включает в себя арифметику, сравнения, (большинство) сокращений, изменение формы (например, поворот), объединений и групповых операций. Просмотрите документацию по основным функциям, чтобы найти подходящий векторизованный метод для вашей проблемы.

Если ничего не существует, не стесняйтесь писать свои собственные, используя собственные расширения Cython .


Следующая лучшая вещь: список понимания

Следующее понимание списка должно быть вашим следующим портом захода, если 1) нет доступного векторизованного решения, 2) производительность важна, но недостаточно важна для того, чтобы пройти через процесс кефонизации вашего кода, и 3) вы пытаетесь выполнить поэлементное преобразование в вашем коде. Существует достаточно доказательств того, что составление списков является достаточно быстрым (и даже иногда более быстрым) для многих общих задач панд.

Формула проста,

# 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
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]

Если вы можете инкапсулировать свою бизнес-логику в функцию,вы можете использовать понимание списка,который вызывает ее.Вы можете заставить произвольно сложные вещи работать за счет простоты и скорости сырого питона.


Очевидный пример

Давайте продемонстрировать разницу с помощью простого примера добавления двух панд столбцов A + B . Это векторизованный оперон, поэтому будет легко сравнить производительность методов, описанных выше.

enter image description here

Код для сравнения,для справки.

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


Дальнейшее чтение

* Строковые методы панд "векторизованы" в том смысле, что они указаны в серии, но работают с каждым элементом. Базовые механизмы все еще итеративны, потому что строковые операции по своей природе трудно векторизовать.


Почему я написал этот ответ

Обычная тенденция, которую я замечаю у новых пользователей, - это задавать вопросы в форме «как я могу перебрать свой df, чтобы сделать X?». Отображение кода, который вызывает iterrows() при выполнении чего-либо внутри цикла for. Вот почему. Новый пользователь библиотеки, который не был ознакомлен с концепцией векторизации, скорее всего, представит код, который решает их проблему, как перебирая свои данные, чтобы что-то сделать. Не зная, как перебирать DataFrame, первое, что они делают, - это Google и в конечном итоге здесь, на этот вопрос. Затем они видят принятый ответ, говорящий им, как это сделать, и закрывают глаза и запускают этот код, не задавая вопросов, если итерация не является правильной вещью.

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




Answer 4 Wes McKinney


Вы должны использовать df.iterrows() . Хотя итерация строка за строкой не особенно эффективна, поскольку нужно создавать объекты Series .




Answer 5 e9t


Хотя iterrows() является хорошим вариантом, иногда itertuples() может быть намного быстрее:

df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})

%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop

%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop