Поведение базовой итерации по объектам pandas
зависит от типа. При итерации по Series
, он рассматривается как массив, и базовая итерация создает значения. DataFrame
следуют соглашению о переборе "ключей" объектов.
Короче говоря, итерация for i in object:
по объекту:
Series
: возвращает значения;DataFrame
: возвращает метки/имена столбцов.Так, например, итерация по DataFrame
дает имена столбцов:
import pandas as pd import numpy as np df = pd.DataFrame( {"col1": np.random.randn(3), "col2": np.random.randn(3)}, index=["a", "b", "c"] ) for col in df: print(col) # col1 # col2
Объекты pandas
также имеют метод .Items()
, похожий на dict.Items()
, для перебора пар (key, value)
.
Для итерации по строкам DataFrame
можно использовать следующие методы:
DataFrame.iterrows()
: перебирает строки DataFrame
как пары (index, Series)
. При этом строки преобразуются в объекты Series
, что может изменить dtypes
и имеет некоторые последствия для производительности.DataFrame.itertuples()
: перебирает строки DataFrame
в виде именованных кортежей значений. Это намного быстрее, чем DataFrame.iterrows()
, и в большинстве случаев предпочтительнее использовать для перебора значений DataFrame
.Предупреждение. Итерация по объектам
pandas
, как правило, выполняется медленно. Во многих случаях итерация вручную по строкам не требуется, и ее можно избежать с помощью одного из следующих подходов:
- Ищите векторизованное решение: многие операции можно выполнять с помощью встроенных методов или функций
NumPy
, (логической) индексации, и т.д.- Если есть функция, которая не может работать со всем
DataFrame
/Series
сразу, лучше использовать методы.apply()
или .map() вместо итерации по значениям.Предупреждение. В зависимости от типов данных, итератор возвращает копию, а не представление, и запись в него не будет иметь никакого эффекта! НЕ изменяйте объект итерации. Не гарантируется, что это сработает во всех случаях.
Например, в следующем случае установка значения не имеет никакого эффекта:
df = pd.DataFrame({"a": [1, 2, 3], "b": ["a", "b", "c"]}) for index, row in df.iterrows(): row["a"] = 10 >>> df # a b # 0 1 a # 1 2 b # 2 3 c
.items()
В соответствии с dict
-подобным интерфейсом, метод dict.items()
выполняет итерацию по парам ключ-значение:
Series.items()
возвращает пары (index, value)
;DataFrame.items()
возвращает пары (column, Series)
.>>> df = pd.DataFrame({"a": [1, 2, 3], "b": ["a", "b", "c"]}) >>> for label, ser in df.items(): ... print('label =>', label) ... print(ser) ... # label => a # 0 1 # 1 2 # 2 3 # Name: a, dtype: int64 # label => b # 0 a # 1 b # 2 c # Name: b, dtype: object
DataFrame.iterrows()
Метод DataFrame.iterrows()
позволяет выполнять итерацию по строкам DataFrame
как по объектам Series
. Он возвращает итератор, возвращающий каждое значение индекса вместе с Series, содержащим данные в каждой строке:
>>> df = pd.DataFrame({"a": [1, 2, 3], "b": ["a", "b", "c"]}) >>> for row_index, row in df.iterrows(): ... print(f'Индекс строки: {row_index}', row, sep="\n") ... # Индекс строки: 0 # a 1 # b a # Name: 0, dtype: object # Индекс строки: 1 # a 2 # b b # Name: 1, dtype: object # Индекс строки: 2 # a 3 # b c # Name: 2, dtype: object
Примечание Так как
DataFrame.iterrows()
возвращаетSeries
для каждой строки, он не сохраняетdtypes
в строках (dtypes
сохраняются в столбцах дляDataFrames
). Например:>>> df_orig = pd.DataFrame([[1, 1.5]], columns=["int", "float"]) >>> df_orig.dtypes # int int64 # float float64 # dtype: object >>> row = next(df_orig.iterrows())[1] >>> row # int 1.0 # float 1.5 # Name: 0, dtype: float64Все значения в строке, возвращаемые в виде
Series
, теперь приводятся к числам с плавающей запятой, а также исходному целочисленному значению в столбцеx
:>>> row["int"].dtype # dtype('float64') >>> df_orig["int"].dtype # dtype('int64')Чтобы сохранить
dtypes
при переборе строк, лучше использоватьDataFrame.itertuples()
, который возвращает именованные кортежи значений и который, как правило, намного быстрее, чемDataFrame.iterrows()
.
DataFrame.itertuples()
Метод DataFrame.itertuples()
вернет итератор, возвращающий именованный кортеж для каждой строки в DataFrame
. Первым элементом кортежа будет соответствующее значение индекса строки, а остальные значения - значения строки.
Например:
>>> df = pd.DataFrame({"a": [1, 2, 3], "b": ["a", "b", "c"]}) >>> for row in df.itertuples(): ... print(row) ... # Pandas(Index=0, a=1, b='a') # Pandas(Index=1, a=2, b='b') # Pandas(Index=2, a=3, b='c')
Этот метод не преобразует строку в объект Series
, он просто возвращает значения внутри именованного кортежа. Таким образом, DataFrame.itertuples()
сохраняет тип данных значений и, как правило, работает быстрее, чем DataFrame.iterrows()
.
Заметка. Если имена столбцов не являются допустимыми идентификаторами Python, то они будут переименованы в позиционные имена. При большом количестве столбцов (>255) возвращаются обычные кортежи.