Как можно перебирать строки в Pandas DataFrame и получать доступ к значениям столбцов по имени?
У меня есть DataFrame df:
c1 c2
0 10 100
1 11 110
2 12 120
Как мне перебирать строки этого DataFrame? Для каждой строки я хочу получать доступ к её элементам (значениям в ячейках) по имени столбца. Например:
for row in df.rows:
print(row['c1'], row['c2'])
Я нашёл похожий вопрос, в котором предлагается использовать один из этих подходов:
for date, row in df.T.iteritems():
или
for row in df.iterrows():
Но я не понимаю, что представляет собой объект row и как с ним работать.
Для итерации по строкам в DataFrame Pandas и доступа к значениям столбцов по имени можно использовать методы iterrows() или itertuples(). При использовании iterrows() каждая итерация возвращает пару (индекс, Series), где Series содержит значения строки с именами столбцов в качестве индекса, что позволяет получать значения с помощью row['имя_столбца']. Для лучшей производительности itertuples() возвращает именованные кортежи, в которых можно получать значения с помощью точечной нотации, такой как row.имя_столбца или индексации кортежа.
Содержание
- Использование iterrows()
- Использование itertuples()
- Сравнение производительности
- Лучшие практики и альтернативы
- Полные примеры
Использование iterrows()
Метод iterrows() является наиболее прямым подходом для начинающих. Он возвращает итератор, который выдает пары (индекс, строка), где:
индекс- это метка индекса строкистрока- это объект pandas Series, содержащий значения строки с именами столбцов в качестве индекса
Для вашего DataFrame можно получить доступ к значениям столбцов с помощью синтаксиса, похожего на словарь:
for index, row in df.iterrows():
print(f"Строка {index}: c1 = {row['c1']}, c2 = {row['c2']}")
Что представляет собой объект row:
При использовании iterrows() каждая строка является объектом pandas Series. Это означает, что вы можете:
- Получать значения по имени столбца с помощью
row['имя_столбца'] - Получать значения по целочисленной позиции с помощью
row[0],row[1]и т.д. - Использовать типичные методы Series, такие как
row.mean(),row.sum()и т.д.
for index, row in df.iterrows():
# Доступ по имени столбца (рекомендуется)
c1_value = row['c1']
c2_value = row['c2']
# Доступ по позиции
c1_value_alt = row[0]
c2_value_alt = row[1]
print(f"Строка {index}: c1 = {c1_value}, c2 = {c2_value}")
Важное замечание: Объект строки, возвращаемый iterrows(), является Series, содержащим копии данных, а не представлениями. Это означает, что вы не можете изменить исходный DataFrame, изменяя объект строки.
Использование itertuples()
Метод itertuples() обычно более эффективен, чем iterrows(). Он возвращает итератор, который выдает именованные кортежи, где каждая строка представлена в виде легковесного именованного кортежа с именами полей, соответствующими именам столбцов.
for row in df.itertuples():
print(f"Строка {row.Index}: c1 = {row.c1}, c2 = {row.c2}")
Что представляет собой объект row:
При использовании itertuples() каждая строка является объектом именованного кортежа с:
row.Index- метка индекса строкиrow.c1- значение столбца ‘c1’ (доступ через атрибут)row.c2- значение столбца ‘c2’ (доступ через атрибут)
Вы можете получать значения с помощью:
- Точечной нотации:
row.имя_столбца(рекомендуется для читаемости) - Позиционной индексации:
row[0],row[1]и т.д.
for row in df.itertuples():
# Доступ по имени атрибута (рекомендуется)
c1_value = row.c1
c2_value = row.c2
# Доступ по позиции
c1_value_alt = row[1] # Примечание: позиция 0 - это Index
c2_value_alt = row[2]
print(f"Строка {row.Index}: c1 = {c1_value}, c2 = {c2_value}")
Преимущества itertuples():
- Более высокая производительность (обычно в 10-15 раз быстрее, чем iterrows)
- Сохранение типов данных во всех строках
- Более эффективное использование памяти
- Более чистый синтаксис с точечной нотацией
Сравнение производительности
Разница в производительности между iterrows() и itertuples() значительна, особенно для больших наборов данных:
import pandas as pd
import time
# Создаем более большой DataFrame для тестирования производительности
df_large = pd.DataFrame({'c1': range(1000000), 'c2': range(1000000, 2000000)})
# Тестируем iterrows()
start_time = time.time()
for index, row in df_large.iterrows():
pass # Просто итерация
iterrows_time = time.time() - start_time
print(f"Время выполнения iterrows(): {iterrows_time:.4f} секунд")
# Тестируем itertuples()
start_time = time.time()
for row in df_large.itertuples():
pass # Просто итерация
itertuples_time = time.time() - start_time
print(f"Время выполнения itertuples(): {itertuples_time:.4f} секунд")
print(f"itertuples() в {iterrows_time/itertuples_time:.1f} раз быстрее")
Результаты производительности:
iterrows(): Медленнее, так как создает новые объекты Series для каждой строкиitertuples(): Быстрее, так как возвращает легковесные именованные кортежи- Для DataFrame с 1M строк:
itertuples()обычно в 10-15 раз быстрее, чемiterrows()
Согласно документации pandas: “Чтобы сохранять типы данных при итерации по строкам, лучше использовать itertuples(), который возвращает именованные кортежи значений и который обычно намного быстрее, чем iterrows()”
Лучшие практики и альтернативы
Когда использовать методы итерации:
Используйте iterrows(), когда:
- Вам нужно изменять данные строк (хотя это обычно не рекомендуется)
- Вы работаете с небольшими наборами данных (<10 000 строк)
- Вам нужны специфические для Series методы во время итерации
Используйте itertuples(), когда:
- Вы работаете со средними и большими наборами данных
- Важна производительность
- Вы хотите иметь чистый, читаемый код с точечной нотацией
- Вы только читаете данные (не изменяете их)
Соображения производительности:
Для больших наборов данных рассмотрите эти альтернативы итерации по строкам:
- Векторизованные операции (Рекомендуется):
# Вместо итерации для вычисления нового столбца
result = df['c1'] * df['c2']
# Вместо итерации для фильтрации
filtered_df = df[df['c1'] > 11]
- Списковые включения:
# Для создания списков из столбцов
c1_values = [row.c1 for row in df.itertuples()]
- Методы Apply:
# Для применения функций к столбцам
df['c1_squared'] = df['c1'].apply(lambda x: x**2)
Важные предостережения:
Никогда не изменяйте то, по чему вы итерируетесь - это не гарантированно будет работать во всех случаях. В зависимости от типов данных, итератор возвращает копию, а не представление, и запись в него не окажет эффекта. Источник
Полные примеры
Пример 1: Базовая итерация по строкам с iterrows()
import pandas as pd
# Создаем DataFrame
df = pd.DataFrame({
'c1': [10, 11, 12],
'c2': [100, 110, 120]
})
print("Исходный DataFrame:")
print(df)
print("\nИспользование iterrows():")
for index, row in df.iterrows():
print(f"Строка {index}: c1 = {row['c1']}, c2 = {row['c2']}")
Пример 2: Базовая итерация по строкам с itertuples()
print("Использование itertuples():")
for row in df.itertuples():
print(f"Строка {row.Index}: c1 = {row.c1}, c2 = {row.c2}")
Пример 3: Практическое применение - Фильтрация и преобразование
# Использование iterrows() для фильтрации
print("\nФильтрация строк, где c1 > 11, с использованием iterrows():")
for index, row in df.iterrows():
if row['c1'] > 11:
print(f"Найдено: c1 = {row['c1']}, c2 = {row['c2']}")
# Использование itertuples() для создания новых данных
print("\nСоздание списка значений c2 с использованием itertuples():")
c2_values = [row.c2 for row in df.itertuples()]
print(c2_values)
Пример 4: Работа с разными типами столбцов
# DataFrame со смешанными типами данных
df_mixed = pd.DataFrame({
'name': ['Алиса', 'Боб', 'Чарли'],
'age': [25, 30, 35],
'salary': [50000.50, 60000.75, 70000.00],
'is_employed': [True, False, True]
})
print("\nСмешанный DataFrame с разными типами данных:")
print(df_mixed)
print("\nИтерация по смешанному DataFrame:")
for row in df_mixed.itertuples():
print(f"{row.name} (возраст {row.age}) зарабатывает ${row.salary:.2f}, работает: {row.is_employed}")
Заключение
Успешная итерация по строкам в DataFrame Pandas и доступ к значениям столбцов по имени становятся простыми, как только вы понимаете два основных подхода:
- Используйте
iterrows()для простых случаев с небольшими наборами данных, когда вам нужны методы Series - Используйте
itertuples()для лучшей производительности и более чистого кода, особенно со средними и большими наборами данных
Ключевые выводы:
iterrows()возвращает пары(индекс, Series)- получайте значения с помощьюrow['имя_столбца']itertuples()возвращает именованные кортежи - получайте значения с помощьюrow.имя_столбцаitertuples()значительно быстрее (в 10-15 раз) и более эффективен по памяти- Для производственного кода с большими наборами данных рассмотрите векторизованные операции вместо итерации по строкам
- Никогда не изменяйте значения DataFrame во время итерации - это приводит к непредсказуемому поведению
Выбор между этими методами зависит от ваших конкретных потребностей, но в большинстве случаев itertuples() обеспечивает наилучший баланс между производительностью и читаемостью.
Источники
- Python Pandas iterate over rows and access column names - Stack Overflow
- pandas.DataFrame.iterrows — pandas 2.3.3 documentation
- How to Iterate Over Rows with Pandas – Loop Through a Dataframe
- Pandas Iterate Over Rows with Examples - Spark By {Examples}
- Iterating over rows and columns in Pandas DataFrame - GeeksforGeeks
- How can I iterate over rows in a Pandas DataFrame? - Stack Overflow
- Pandas DataFrame itertuples() Method - GeeksforGeeks
- Panda DataFrames - iterrows vs itertuples