6 трюков в Pandas, которые сэкономят время

6 трюков в Pandas, которые сэкономят время

Мария Жарова | t.me/data_easy

Когда только начинаешь работать с данными, кажется, что всё сводится к .groupby()for-циклам и магическому df[df["col"] == "val"]. Но потом приходит понимание: эффективность в деталях.

Вот 6 трюков в Pandas, которые сэкономят вам часы рутины и сделают код чище, быстрее и понятнее. Некоторые почти незаметные, но очень мощные. Поехали!

1. map() и apply() — когда и что?

Для одного столбца всегда выбирайте map() — он быстрее и проще. Особенно если используете словарь или простую функцию:

df["gender_code"] = df["gender"].map({"male": 0, "female": 1}) df["name_len"] = df["name"].map(len)

Почему это работает быстрее, чем apply()?

Потому что map() оптимизирован для Series: он напрямую применяет функцию к каждому элементу, без лишних обёрток и лишнего контроля.

Но! Если вам нужно работать с несколькими колонками одновременно, без apply() не обойтись:

df["full_name"] = df.apply(lambda row: f"{row['first']} {row['last']}", axis=1)

2. query() — фильтрация как в SQL

Любителям SQL этот синтаксис точно понравится:

df.query("age > 25 and city == 'Moscow'")

Выглядит лучше, читается легче, особенно когда много условий.

Под капотом это тот же фильтр, что и df[(df["age"] > 25) & (df["city"] == "Moscow")],

по производительности почти одинаково, но писать и читать query() иногда гораздо приятнее:)

Внутри можно также использовать переменные:

age_limit = 25
df.query("age > @age_limit")

3. isin() — фильтрация по списку значений

К слову, если хотите отобрать строки, где значения для фильтрации содержатся в списке, isin() вам в помощь:

df[df["category"].isin(["books", "electronics"])]

Инверсия (not in) делается просто:

df[~df["user_id"].isin(blacklist)]

Читается лучше, чем громоздкие цепочки | и ==.

4. assign() — новые столбцы в цепочках

Иногда хочется, чтобы код читалcя плавно, без лишних отвлекающих строк и вкраплений вроде df["col"] = ...посреди пайплайна. В этом может помочь assign(), сравните код до:

df["total"] = df["price"] * df["quantity"]
df = df[df["total"] > 1000]

и после:

df = (
  df
  .assign(total=lambda x: x["price"] * x["quantity"])
  .query("total > 1000")
)

Красота, да и ничего не потеряется.

5. pipe() — для тех, кто любит пайплайны

Когда сама цепочка трансформаций становится длинной, хочется сохранить плавный поток операций без вложенных функций и промежуточных переменных. Тут на помощь приходит .pipe().

Он передаёт датафрейм как первый аргумент в функцию. Это удобно, если приходится писать кастомные функции для обработки данных, но хочется использовать их прямо в цепочке:

def clean_text(df):
  df["text"] = df["text"].str.lower()
  return df

def add_features(df, some_param):
  df["length"] = df["text"].str.len() * some_param
  return df

df = (
  df
  .pipe(clean_text)
  .pipe(add_features, some_param=10)
)

Полезная вещь, если строите многоступенчатые преобразования.

6. nlargest() и nsmallest() — топ по колонке

Вместо этого:

df.sort_values("revenue", ascending=False).head(5)

можно написать так:

df.nlargest(5, "revenue")

а если нужны значения с другого отсортированного "конца", то так тоже можно:

df.nsmallest(3, "error_rate")


Каждый из этих методов поначалу кажется просто «альтернативным синтаксисом». Но вместе они превращают Pandas-код из «скрипта для себя» в читаемый, поддерживаемый и быстрый пайплайн⚡.




Report Page