Почему iterrows() в pandas почти всегда плохая идея
Когда нужно пройти по строкам DataFrame, многие пишут так:
import pandas as pd
df = pd.DataFrame({
"name": ["Alice", "Bob", "Charlie"],
"score": [85, 92, 78]
})
# Проходим по строкам
for index, row in df.iterrows():
# row — это объект Series
# можно обращаться к значениям по имени столбца
if row["score"] >= 90:
print(f"{row['name']} — отличный результат")
На первый взгляд всё выглядит логично: мы перебираем строки и работаем с ними как с объектами. Но у такого подхода есть несколько серьёзных проблем.
Почему iterrows() плохо масштабируется
Главная проблема – потеря производительности.
Когда используется iterrows():
• каждая строка превращается в объект Series
• создаётся новый объект Python
• цикл выполняется на уровне Python
То есть мы фактически превращаем pandas в обычный for-цикл.
А pandas создан именно для векторных операций, которые выполняются гораздо быстрее.
Как это обычно можно переписать
Представим, что нам нужно выбрать всех пользователей с высоким баллом.
Вместо цикла:
# медленный подход
for index, row in df.iterrows():
if row["score"] >= 90:
print(row["name"])
Можно сделать одну векторную операцию:
# быстрый и "пандовский" способ
high_scores = df[df["score"] >= 90]
print(high_scores["name"])
Что здесь происходит:
• создаётся логическая маска df["score"] >= 90
• pandas применяет её ко всему столбцу сразу
• никакого Python-цикла не требуется
На больших таблицах разница может быть в десятки раз по скорости.
Когда iterrows() всё же можно использовать
Иногда без него не обойтись.
Например:
• при сложной логике, которую трудно векторизовать
• при работе с внешними API
• при отладке данных
Но даже в этих случаях лучше сначала подумать, можно ли решить задачу через операции над колонками.
Главное правило
Если вы пишете iterrows() — почти всегда есть более быстрый и простой способ.
В pandas стоит мыслить не строками, а столбцами.
И именно это делает код:
• быстрее
• короче
• более «пандовским».