У меня есть DataFrame
от панды:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Вывод:
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():
или
for row in df.iterrows():
Но я не понимаю, что это за row
объект и как я могу с ним работать.
iter*
функции следует использовать в очень редких случаях. Также связано .iterrows
, есть лучшие способы перебора DataFrame, вы можете просто перебрать список списков на этом этапе. Если вы находитесь в точке, где вы ничего не делаете, кроме как перебираете DataFrames, использование DataFrame на самом деле не имеет никакой пользы (если вы перебираете его, это единственное, что вы делаете с ним). Просто мой 2с.pandas
это выбор чтения файла CSV, даже если набор данных небольшой. Программировать данные проще с помощью API-интерфейсовОтветы:
DataFrame.iterrows - это генератор, который выдает как индекс, так и строку
источник
431341610650
читаются как4.31E+11
. Есть ли способ сохранить dtypes?itertuples
, как описано ниже. См. Также pandas.pydata.org/pandas-docs/stable/generated/…Ответ: НЕ * !
Итерации в пандах - это анти-паттерн, и вы должны делать это только тогда, когда исчерпали все остальные опции. Вы не должны использовать какую-либо функцию с "
iter
" в названии более нескольких тысяч строк, иначе вам придется привыкнуть к большим ожиданиям.Хотите распечатать DataFrame? Использование
DataFrame.to_string()
.Вы хотите что-то вычислить? В этом случае ищите методы в следующем порядке (список изменен здесь ):
for
петля)DataFrame.apply()
: i) Сокращения, которые могут быть выполнены в Cython, II) Итерация в пространстве PythonDataFrame.itertuples()
а такжеiteritems()
DataFrame.iterrows()
iterrows
иitertuples
(оба получают много голосов в ответах на этот вопрос) следует использовать в очень редких случаях, таких как создание объектов строк / именных кортежей для последовательной обработки, что на самом деле является единственной вещью, для которой эти функции полезны.Обращение к власти
На странице документации по итерации есть огромное красное окно с предупреждением:
* Это на самом деле немного сложнее, чем «нет».
df.iterrows()
это правильный ответ на этот вопрос, но «векторизация ваших операций» лучше. Я признаю, что существуют обстоятельства, в которых нельзя избежать итерации (например, некоторые операции, в которых результат зависит от значения, вычисленного для предыдущей строки). Однако для того, чтобы узнать, когда это нужно, нужно некоторое знакомство с библиотекой. Если вы не уверены, нужно ли вам итеративное решение, скорее всего, нет. PS: Чтобы узнать больше о моем обосновании написания этого ответа, перейдите к самому низу.Быстрее, чем зацикливание: векторизация , Cython
Большое количество базовых операций и вычислений "векторизовано" пандами (либо через NumPy, либо через функции Cythonized). Это включает в себя арифметику, сравнения, (большинство) сокращений, изменение формы (например, поворот), объединений и групповых операций. Просмотрите документацию по основным функциям, чтобы найти подходящий векторизованный метод для вашей проблемы.
Если ничего не существует, не стесняйтесь писать свои собственные, используя собственные расширения Cython .
Следующая лучшая вещь: список понимания *
Следующее понимание списка должно быть вашим следующим портом захода, если 1) нет доступного векторизованного решения, 2) производительность важна, но недостаточно важна для того, чтобы пройти через процесс кефонизации вашего кода, и 3) вы пытаетесь выполнить поэлементное преобразование в вашем коде. Существует множество доказательств того, что составление списков является достаточно быстрым (и даже иногда более быстрым) для многих обычных задач панд.
Формула проста,
Если вы можете инкапсулировать свою бизнес-логику в функцию, вы можете использовать понимание списка, которое ее вызывает. Вы можете заставить произвольно сложные вещи работать благодаря простоте и скорости необработанного Python.
Понятия Caveats
List предполагают, что с вашими данными легко работать - это означает, что ваши типы данных согласованы и у вас нет NaN, но это не всегда может быть гарантировано.
zip(df['A'], df['B'], ...)
вместо того,df[['A', 'B']].to_numpy()
чтобы последний неявно преобразовывал данные в наиболее распространенный тип. Например, если A числовое, а B строковое,to_numpy()
приведёт весь массив к строковому, что может быть не тем, что вы хотите. К счастью,zip
объединить ваши столбцы - это самый простой обходной путь.* YMMV по причинам, изложенным в разделе « Предостережения » выше.
Очевидный пример
Продемонстрируем разницу на простом примере добавления двух столбцов панд
A + B
. Это векторизованный оперон, поэтому будет легко сравнить производительность методов, описанных выше.Код для сравнения, для вашей справки. Линия внизу измеряет функцию, написанную на numpandas, стиле панд, который сильно смешивается с numpy, чтобы выжать максимальную производительность. Написание кода numpandas следует избегать, если вы не знаете, что делаете. Придерживайтесь API, где вы можете (то есть, предпочитаете
vec
болееvec_numpy
).Я должен отметить, однако, что это не всегда так сухо. Иногда ответ «что является лучшим методом для операции» - «это зависит от ваших данных». Мой совет, чтобы проверить различные подходы к вашим данным, прежде чем остановиться на одном.
Дальнейшее чтение
10 минут на панд и основные функциональные возможности - полезные ссылки, которые знакомят вас с пандами и их библиотекой векторизованных * / цитонизированных функций.
Повышение производительности - учебник из документации по расширению стандартных операций с пандами
Неужели петли в пандах действительно плохие? Когда я должен заботиться? - подробное описание мной списков и их пригодности для различных операций (в основном с нечисловыми данными)
Когда мне нужно использовать pandas apply () в моем коде? -
apply
медленный (но не такой медленный, как вiter*
семье. Однако бывают ситуации, когда можно (или нужно) рассматриватьapply
как серьезную альтернативу, особенно в некоторыхGroupBy
операциях).* Строковые методы панд "векторизованы" в том смысле, что они указаны в серии, но работают с каждым элементом. Базовые механизмы все еще итеративны, потому что строковые операции по своей природе трудно векторизовать.
Почему я написал этот ответ
Обычная тенденция, которую я замечаю у новых пользователей, - это задавать вопросы в форме «как я могу перебрать свой df, чтобы сделать X?». Отображение кода, вызывающего
iterrows()
при выполнении чего-либо внутри цикла for. Вот почему. Новый пользователь библиотеки, который не был ознакомлен с концепцией векторизации, скорее всего, представит код, который решает их проблему, как перебирая свои данные, чтобы что-то сделать. Не зная, как перебирать DataFrame, первое, что они делают, - это Google и в конечном итоге здесь, на этот вопрос. Затем они видят принятый ответ, говорящий им, как это сделать, и закрывают глаза и запускают этот код, даже не задавая вопрос, является ли итерация неправильной вещью.Цель этого ответа состоит в том, чтобы помочь новым пользователям понять, что итерация не обязательно является решением каждой проблемы, и что могут существовать лучшие, более быстрые и более идиоматические решения, и что стоит потратить время на их изучение. Я не пытаюсь начать войну итераций против векторизации, но я хочу, чтобы новые пользователи были информированы при разработке решений своих проблем с этой библиотекой.
источник
zip(df['A'], df['B'])
вместоdf.iterrows()
.iterrows()
и неявно осудить итерацию, если и когда существуют лучшие альтернативы.for
сами по себе циклы в порядке, но списки лучше, если вы итеративно выполняете поэлементные преобразования.DataFrame.values
каждый столбец будет преобразован в общий тип данных.DataFrame.to_numpy()
делает это тоже. К счастью, мы можем использоватьzip
любое количество столбцов.Сначала подумайте, действительно ли вам нужно перебирать строки в DataFrame. Смотрите этот ответ для альтернатив.
Если вам все еще нужно перебирать строки, вы можете использовать методы ниже. Обратите внимание на некоторые важные предостережения, которые не упоминаются ни в одном из других ответов.
DataFrame.iterrows ()
DataFrame.itertuples ()
itertuples()
должен быть быстрее чемiterrows()
Но имейте в виду, согласно документам (панды 0.24.2 на данный момент):
iterrows:
dtype
может не совпадать от строки к строкеiterrows: не изменять строки
Вместо этого используйте DataFrame.apply () :
itertuples:
Смотрите pandas docs на итерации для более подробной информации.
источник
for row in df[['c1','c2']].itertuples(index=True, name=None):
включения только определенных столбцов в итератор строк.getattr(row, "c1")
, вы можете использовать толькоrow.c1
.getattr(row, "c1")
вместо этогоrow.c1
, вы потеряете любое преимущество в производительностиitertuples
, и если вам действительно нужно получить свойство через строку, вы должны использовать вместо него iterrows.numba
иcython
(одни и те же документы говорят, что «в Python всегда стоит оптимизировать в первую очередь»). Я написал этот ответ, чтобы помочь другим избежать (иногда расстраивающих) проблем, поскольку ни один из других ответов не упоминает эти предостережения. Вводить кого-либо в заблуждение или говорить «это правильно» никогда не было моим намерением. Я улучшил ответ.Вы должны использовать
df.iterrows()
. Хотя итерация строка за строкой не особенно эффективна, так какSeries
объекты должны быть созданы.источник
Хотя
iterrows()
это хороший вариант, иногдаitertuples()
может быть гораздо быстрее:источник
for a,b,c in izip(df["a"],df["b"],df["c"]:
почти одинаково быстро.iterrows()
каждую строку данных в Серию, аitertuples()
не делает.df
создается из словаря, поэтомуrow[1]
может ссылаться на любой из столбцов. Как оказалось, время примерно одинаковое для целого числа и столбцов с плавающей точкой.Вы также можете использовать
df.apply()
для перебора строк и доступа к нескольким столбцам для функции.документы: DataFrame.apply ()
источник
apply
он не «повторяется» над строками, скорее он применяет функцию по строкам. Приведенный выше код не будет не работать , если вы действительно делаете итерации нужна , и индексы, например , при сравнении значений в разных строках (в этом случае вы можете сделать ничего , кроме итерацию).Вы можете использовать функцию df.iloc следующим образом:
источник
itertuples
сохраняет типы данных, но избавляется от любого имени, которое ему не нравится.iterrows
делает обратное.for i in range(df.shape[0])
может немного ускорить этот подход, он все равно примерно в 3,5 раза медленнее, чем описанный выше подход iterrows () для моего приложения.my_iter = df.itertuples()
занимает вдвое больше памяти и много времени для ее копирования. то же самое дляiterrows()
.Я искал Как перебирать строки и столбцы и закончил вот так:
источник
Вы можете написать свой собственный итератор, который реализует
namedtuple
Это прямо сопоставимо с
pd.DataFrame.itertuples
. Я стремлюсь выполнить ту же задачу с большей эффективностью.Для данного кадра данных с моей функцией:
Или с
pd.DataFrame.itertuples
:Комплексный тест
Мы тестируем доступность всех столбцов и подмножество столбцов.
источник
intertuples
, что оранжевая линия - это список итераторов в блоке yield.interrows
не сравнивается.Как эффективно выполнять итерации?
Если вам действительно нужно итерировать кадр данных pandas, вы, вероятно, захотите избегать использования iterrows () . Существуют разные методы, и обычный
iterrows()
далеко не самый лучший. itertuples () может быть в 100 раз быстрее.Короче говоря:
df.itertuples(name=None)
. В частности, когда у вас фиксированное число столбцов и менее 255 столбцов. Смотрите пункт (3)df.itertuples()
кроме случаев, когда в ваших столбцах есть специальные символы, такие как пробелы или '-'. Смотрите пункт (2)itertuples()
даже если ваш фрейм данных имеет странные столбцы, используя последний пример. Смотрите пункт (4)iterrows()
если вы не можете предыдущие решения. Смотрите пункт (1)Различные методы итерации по строкам в фрейме данных pandas:
Создайте случайный кадр данных с миллионом строк и 4 столбцами:
1) Обычное
iterrows()
удобно, но чертовски медленно:2) По умолчанию
itertuples()
уже намного быстрее, но он не работает с именами столбцов, такими какMy Col-Name is very Strange
(вы должны избегать этого метода, если ваши столбцы повторяются или если имя столбца не может быть просто преобразовано в имя переменной Python) .:3) Использование по умолчанию
itertuples()
name = None еще быстрее, но не очень удобно, поскольку вы должны определить переменную для каждого столбца.4) Наконец, named
itertuples()
медленнее, чем предыдущая точка, но вам не нужно определять переменную для каждого столбца, и он работает с именами столбцов, такими какMy Col-Name is very Strange
.Вывод:
Эта статья представляет собой очень интересное сравнение между iterrows и itertuples
источник
Чтобы зациклить все строки в
dataframe
вы можете использовать:источник
источник
Иногда полезный шаблон:
Что приводит к:
источник
Чтобы зациклить все строки в a
dataframe
и удобно использовать значения каждой строки , их можно преобразовать в s. Например:namedtuples
ndarray
Итерация по строкам:
результаты в:
Обратите внимание , что если
index=True
, индекс добавляется в качестве первого элемента кортежа , который может быть нежелательным для некоторых применений.источник
Существует способ перебрасывать строки броска при получении взамен DataFrame, а не Series. Я не вижу никого, кто упомянул бы, что вы можете передать index в виде списка для строки, которая будет возвращена как DataFrame:
Обратите внимание на использование двойных скобок. Это возвращает DataFrame с одной строкой.
источник
Для просмотра и изменения значений я бы использовал
iterrows()
. В цикле for и с помощью распаковки кортежей (см. Пример:)i, row
я используюrow
только для просмотра значения и использованияi
сloc
методом, когда я хочу изменить значения. Как указано в предыдущих ответах, здесь вы не должны изменять то, что вы повторяете.Здесь
row
в цикле есть копия этой строки, а не ее представление. Таким образом, вы не должны писать что-то вродеrow['A'] = 'New_Value'
, это не будет изменять DataFrame. Тем не менее, вы можете использоватьi
иloc
и указать DataFrame для выполнения работы.источник
Я знаю, что опаздываю на автоответчик, но я просто хотел добавить к ответу @ cs95 выше, который, я считаю, должен быть принятым ответом. В своем ответе он показывает, что векторизация панд намного превосходит другие методы панд для вычисления данных с помощью фреймов данных.
Я хотел бы добавить, что если вы сначала преобразуете фрейм данных в массив numpy, а затем используете векторизацию, это даже быстрее, чем векторизация пандасов фреймов данных (и это включает время, чтобы превратить его обратно в серию фреймов данных).
Если вы добавите следующие функции в тестовый код @ cs95, это станет довольно очевидным:
источник
Вы также можете сделать
numpy
индексирование для еще большего ускорения. На самом деле это не итерация, но она работает намного лучше, чем итерация для определенных приложений.Вы также можете привести его к массиву. Предполагается, что эти индексы / выборки уже действуют как массивы Numpy, но я столкнулся с проблемами и должен был разыграть
источник
Существует много способов перебора строк в панде. Один очень простой и интуитивно понятный способ:
источник
В этом примере iloc используется для выделения каждой цифры в кадре данных.
источник
Некоторые библиотеки (например, библиотека взаимодействия Java, которую я использую) требуют, чтобы значения передавались подряд по очереди, например, при потоковой передаче данных. Чтобы воспроизвести потоковую природу, я «поочередно» перенаправляю значения своих данных в рамку, я написал ниже, что время от времени пригодится.
Который может быть использован:
И сохраняет сопоставление значений / имен для итерируемых строк. Очевидно, это намного медленнее, чем использовать apply и Cython, как указано выше, но это необходимо в некоторых обстоятельствах.
источник
Короче говоря
Подробности в этом видео
эталонный тест
источник