Нашли ошибку?
базовыйpandas 3.0.6

Частые ошибки

Двенадцать ошибок, которые чаще всего встречаются в коде с pandas, — и как их исправить.

Содержание статьи

Каждая ошибка показана парой: как не надо и как надо. Подробности — в статье по ссылке.

Данные для примеровиспользуются во всех примерах ниже
sales = pd.DataFrame({
    "city": ["Омск", "Тула", None, "Омск"],
    "cups": [30, 12, 18, 25],
    "price": [180.0, None, 165.0, 190.0],
    "manager": ["Аня", "Борис", "Вика", "Аня"],
})

Цепочечное присваивание

Две пары скобок при записи в pandas 3 никогда не меняют таблицу. → Copy-on-Write

Неправильно
sales["cups"][0] = 100
sales["cups"].tolist()
Вывод
ChainedAssignmentError: A value is being set on a copy of a DataFrame or Series through chained assignment.
Such chained assignment never works to update the original DataFrame or Series, because the intermediate object on which we are setting values always behaves as a copy (due to Copy-on-Write).

Try using '.loc[row_indexer, col_indexer] = value' instead, to perform the assignment in a single step.

See the documentation for a more detailed explanation: https://pandas.pydata.org/pandas-docs/stable/user_guide/copy_on_write.html#chained-assignment
[30, 12, 18, 25]
Правильно
sales.loc[0, "cups"] = 100
sales["cups"].tolist()
Вывод
[100, 12, 18, 25]

and / or в фильтре

→ Фильтрация

Неправильноошибка: ValueError
sales[(sales["cups"] > 15) and (sales["city"] == "Омск")]
Ошибка
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Правильно
sales[(sales["cups"] > 15) & (sales["city"] == "Омск")]
Вывод
   city  cups  price manager
0  Омск    30  180.0     Аня
3  Омск    25  190.0     Аня

Результат метода не сохранили

drop, rename, sort_values, fillna, assign возвращают новую таблицу. → Столбцы

Неправильно
sales.drop(columns=["price"])
sales.columns.tolist()                 # столбец на месте: результат drop потерян
Вывод
['city', 'cups', 'price', 'manager']
Правильно
sales = sales.drop(columns=["price"])
sales.columns.tolist()
Вывод
['city', 'cups', 'manager']

s[0] вместо s.iloc[0]

В квадратных скобках — метка, а не позиция. → Series

Неправильноошибка: KeyError
by_city = sales.set_index("cups")["city"]
by_city[0]                             # 0 — метка, а не позиция
Ошибка
KeyError: 0
Правильно
by_city = sales.set_index("cups")["city"]
by_city.iloc[0]
Вывод
'Омск'

Поиск пропусков через ==

→ Пропуски

Неправильно
sales[sales["price"] == np.nan]        # пусто
Вывод
Empty DataFrame
Columns: [city, cups, price, manager]
Index: []
Правильно
sales[sales["price"].isna()]
Вывод
   city  cups  price manager
1  Тула    12    NaN   Борис

Строки с пустым ключом выпали из groupby

→ groupby

Неожиданно
sales.groupby("city")["cups"].sum().sum(), sales["cups"].sum()   # суммы не сходятся
Вывод
(np.int64(67), np.int64(85))
Правильно
sales.groupby("city", dropna=False)["cups"].sum()
Вывод
city
Омск    55
Тула    12
NaN     18
Name: cups, dtype: int64

mean по всей таблице с текстом

→ Описательная статистика

Неправильноошибка: TypeError
sales.groupby("city", dropna=False).mean()
Ошибка
TypeError: dtype 'str' does not support operation 'mean'
Правильно
sales.groupby("city", dropna=False)[["cups", "price"]].mean()
Вывод
      cups  price
city
Омск  27.5  185.0
Тула  12.0    NaN
NaN   18.0  165.0

merge размножил строки

Ключ в справочнике не уникален. → merge: ключи и проверки

Неправильно
cities = pd.DataFrame({"city": ["Омск", "Омск", "Тула"], "region": ["Сибирь", "Сибирь", "Центр"]})
len(sales), len(sales.merge(cities, on="city", how="left"))   # строк стало больше
Вывод
(4, 6)
Правильно
cities = pd.DataFrame({"city": ["Омск", "Омск", "Тула"], "region": ["Сибирь", "Сибирь", "Центр"]})
sales.merge(cities.drop_duplicates("city"), on="city", how="left", validate="many_to_one")
Вывод
   city  cups  price manager  region
0  Омск    30  180.0     Аня  Сибирь
1  Тула    12    NaN   Борис   Центр
2   NaN    18  165.0    Вика     NaN
3  Омск    25  190.0     Аня  Сибирь

Даты остались строками

→ read_csv, даты

Неправильно
from pathlib import Path
Path("log.csv").write_text("day,visits\n2024-03-01,10\n2024-03-02,12\n")
pd.read_csv("log.csv").dtypes          # даты остались строками
Вывод
day         str
visits    int64
dtype: object
Правильно
from pathlib import Path
Path("log.csv").write_text("day,visits\n2024-03-01,10\n2024-03-02,12\n")
pd.read_csv("log.csv", parse_dates=["day"]).dtypes
Вывод
day       datetime64[us]
visits             int64
dtype: object

Лишний столбец после to_csv

→ read_csv

Неправильно
sales.to_csv("out.csv")
pd.read_csv("out.csv").columns.tolist()   # лишний столбец Unnamed: 0
Вывод
['Unnamed: 0', 'city', 'cups', 'price', 'manager']
Правильно
sales.to_csv("out.csv", index=False)
pd.read_csv("out.csv").columns.tolist()
Вывод
['city', 'cups', 'price', 'manager']

apply и iterrows вместо операций над столбцами

Построчная обработка в сотни раз медленнее векторной. → Функции, почему iterrows медленный

Код из интернета для pandas 1.x и 2.x

applymap, append, fillna(method=…), частоты M / Q / Y, позиционный s[0] удалены или изменили смысл. Обзор — в статье что такое pandas.