Как я могу отфильтровать список в столбце Polars?

Вопрос или проблема

Допустим, у меня есть данные, подобные этим:

import polars as pl

df = pl.DataFrame(
    {
        "subject": ["subject1", "subject2"],
        "emails": [
            ["samATxyz.com", "janeATxyz.com", "jimATcustomer.org"],
            ["samATxyz.com", "zaneATxyz.com", "basATcustomer.org", "jimATcustomer.org"],
        ],
    }
)

df
shape: (2, 2)
┌──────────┬─────────────────────────────────────────────────────────────────────────────┐
│ subject  ┆ emails                                                                      │
│ ---      ┆ ---                                                                         │
│ str      ┆ list[str]                                                                   │
╞══════════╪═════════════════════════════════════════════════════════════════════════════╡
│ subject1 ┆ ["samATxyz.com", "janeATxyz.com", "jimATcustomer.org"]                      │
│ subject2 ┆ ["samATxyz.com", "zaneATxyz.com", "basATcustomer.org", "jimATcustomer.org"] │
└──────────┴─────────────────────────────────────────────────────────────────────────────┘

Я хочу отфильтровать данные, чтобы в столбце emails содержались только электронные адреса, оканчивающиеся на "ATxyz.com".

shape: (2, 2)
┌──────────┬───────────────────────────────────┐
│ subject  ┆ emails                            │
│ ---      ┆ ---                               │
│ str      ┆ list[str]                         │
╞══════════╪═══════════════════════════════════╡
│ subject1 ┆ ["samATxyz.com", "janeATxyz.com"] │
│ subject2 ┆ ["samATxyz.com", "zaneATxyz.com"] │
└──────────┴───────────────────────────────────┘

Как я могу сделать это, используя polars?

У меня было несколько идей, но я не могу разобраться с правильным синтаксисом, или кажется, что это более сложно/подробно, чем я ожидал:

  • Может быть, я мог бы как-то отфильтровать данные, используя .list.eval(pl.element() ..., но я не могу понять, как отфильтровать элементы в списке с помощью этого синтаксиса.
  • Я мог бы изменить форму данных, используя .explode, но это кажется многословным и более сложным, чем нужно.

Это то, что я смог достичь

import polars as pl

df = pl.DataFrame(
    {
        "subject": ["subject1", "subject2"],
        "emails": [
            ["samATxyz.com", "janeATxyz.com", "jimATcustomer.org"],
            ["samATxyz.com", "zaneATxyz.com", "basATcustomer.org", "jimATcustomer.org"],
        ],
    }
)

df.with_columns(
    pl.col("emails").list.eval(pl.element().str.contains("ATxyz")),
)
shape: (2, 2)
┌──────────┬────────────────────────────┐
│ subject  ┆ emails                     │
│ ---      ┆ ---                        │
│ str      ┆ list[bool]                 │
╞══════════╪════════════════════════════╡
│ subject1 ┆ [true, true, false]        │
│ subject2 ┆ [true, true, false, false] │
└──────────┴────────────────────────────┘

Вы были на правильном пути с pl.Expr.list.eval. Это можно комбинировать с pl.Expr.filter, чтобы добиться желаемого результата следующим образом.

df.with_columns(
    pl.col("emails").list.eval(
        pl.element().filter(pl.element().str.ends_with("ATxyz.com"))
    )
)
shape: (2, 2)
┌──────────┬───────────────────────────────────┐
│ subject  ┆ emails                            │
│ ---      ┆ ---                               │
│ str      ┆ list[str]                         │
╞══════════╪═══════════════════════════════════╡
│ subject1 ┆ ["samATxyz.com", "janeATxyz.com"] │
│ subject2 ┆ ["samATxyz.com", "zaneATxyz.com"] │
└──────────┴───────────────────────────────────┘

Ответ или решение

Чтобы отфильтровать список в столбце DataFrame с использованием библиотеки Polars, вы можете воспользоваться выражением pl.Expr.list.eval() и комбинировать его с функцией pl.Expr.filter(). Рассмотрим, как это сделать на примере ваших данных.

Предположим, у вас есть DataFrame с названием df, который содержит два столбца: subject и emails. Столбец emails включает в себя списки адресов электронной почты. Вы хотите отфильтровать этот столбец так, чтобы он содержал только адреса, оканчивающиеся на "ATxyz.com".

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

import polars as pl

# Создание DataFrame
df = pl.DataFrame(
    {
        "subject": ["subject1", "subject2"],
        "emails": [
            ["samATxyz.com", "janeATxyz.com", "jimATcustomer.org"],
            ["samATxyz.com", "zaneATxyz.com", "basATcustomer.org", "jimATcustomer.org"],
        ],
    }
)

# Применение фильтрации к списку в столбце emails
filtered_df = df.with_columns(
    pl.col("emails").list.eval(
        pl.element().filter(pl.element().str.ends_with("ATxyz.com"))
    )
)

# Вывод отфильтрованного DataFrame
print(filtered_df)

При выполнении вышеуказанного кода вы получите следующий вывод:

shape: (2, 2)
┌──────────┬───────────────────────────────────┐
│ subject  ┆ emails                            │
│ ---      ┆ ---                               │
│ str      ┆ list[str]                         │
╞══════════╪═══════════════════════════════════╡
│ subject1 ┆ ["samATxyz.com", "janeATxyz.com"] │
│ subject2 ┆ ["samATxyz.com", "zaneATxyz.com"] │
└──────────┴───────────────────────────────────┘

Таким образом, столбец emails теперь содержит только те адреса, которые заканчиваются на ATxyz.com.

Объяснение:

  • pl.col("emails") выбирает столбец emails.
  • .list.eval(...) применяет функцию к каждому списку в этом столбце.
  • pl.element().filter(...) позволяет фильтровать элементы списка на основе условия, установленного в pl.element().str.ends_with("ATxyz.com"), что проверяет, оканчивается ли каждый адрес электронной почты на указанный домен.

Эта методология является простой и эффективной для выполнения нужной фильтрации в данных Polars.

Оцените материал
Добавить комментарий

Капча загружается...