Обработка нескольких операций над столбцами DataFrame с помощью поляров

Я пытаюсь выбрать все столбцы DataFrame и выполнить несколько операций над каждым столбцом, используя Polars. Например, я обнаружил, что могу использовать следующий код для подсчета ненулевых значений в каждом столбце:

df.select(pl.col("*").is_not_null().sum()

Однако, когда я пытаюсь объединить несколько операций следующим образом:

(
    df
    .select(
        pl.col("*").is_not_null().sum().alias("foo"),
        pl.col("*").is_null().sum().alias("bar")
    )
)

Я сталкиваюсь с Duplicated Error. Кажется, это происходит потому, что Polars пытается выполнить операции, но в конечном итоге использует одни и те же имена столбцов, что вызывает проблему дублирования.

Чтобы обойти эту проблему, я сейчас использую следующий подход:

a = (
    df
    .select(
        pl.col("*").is_null().sum(),

    )
    .transpose(include_header=True)
    .rename(
        {"column_0" : "null_count"}
    )
)

b = (
    df
    .select(
        pl.col("*").is_not_null().sum(),

    )
    .transpose(include_header=True)
    .rename(
        {"column_0" : "not_null_count"}
    )
)

a.join(b, how = "left", on = "column")

Моя цель - создать вывод, который выглядит следующим образом:

shape: (8, 3)
┌─────────────┬────────────┬────────────────┐
│ column      ┆ null_count ┆ not_null_count │
│ ---         ┆ ---        ┆ ---            │
│ str         ┆ u32        ┆ u32            │
╞═════════════╪════════════╪════════════════╡
│ InvoiceNo   ┆ 0          ┆ 541909         │
│ StockCode   ┆ 0          ┆ 541909         │
│ Description ┆ 1454       ┆ 540455         │
│ Quantity    ┆ 0          ┆ 541909         │
│ InvoiceDate ┆ 0          ┆ 541909         │
│ UnitPrice   ┆ 0          ┆ 541909         │
│ CustomerID  ┆ 135080     ┆ 406829         │
│ Country     ┆ 0          ┆ 541909         │
└─────────────┴────────────┴────────────────┘
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Во втором коде все столбцы объединены, поэтому вы можете дать им суффикс name.suffix, если вы хотите сохранить все без повторяющихся имен:

(
    df
    .select(
        pl.col("*").is_not_null().sum().name.suffix('_not_null'),
        pl.col("*").is_null().sum().name.suffix('_null')
    )
)

Выход:

┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐
│ InvoiceNo ┆ StockCode ┆ Descripti ┆ Quantity_ ┆ … ┆ InvoiceDa ┆ UnitPrice ┆ CustomerI ┆ Country_ │
│ _not_null ┆ _not_null ┆ on_not_nu ┆ not_null  ┆   ┆ te_null   ┆ _null     ┆ D_null    ┆ null     │
│ ---       ┆ ---       ┆ ll        ┆ ---       ┆   ┆ ---       ┆ ---       ┆ ---       ┆ ---      │
│ u32       ┆ u32       ┆ ---       ┆ u32       ┆   ┆ u32       ┆ u32       ┆ u32       ┆ u32      │
│           ┆           ┆ u32       ┆           ┆   ┆           ┆           ┆           ┆          │
╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡
│ 90        ┆ 88        ┆ 90        ┆ 87        ┆ … ┆ 14        ┆ 8         ┆ 9         ┆ 8        │
└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘

Теперь, учитывая ваш пример, возможно, не имеет особого смысла подсчитывать все значения NULL И все ненулевые значения, поскольку сумма этих двух равна длине DataFrame.

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

(df.select(pl.col('*').is_null().sum())
   .transpose(include_header=True, column_names=['null_count'])
   .with_columns(not_null_count=len(df)-pl.col('null_count'))
)

Пример вывода:

┌─────────────┬────────────┬────────────────┐
│ column      ┆ null_count ┆ not_null_count │
│ ---         ┆ ---        ┆ ---            │
│ str         ┆ u32        ┆ u32            │
╞═════════════╪════════════╪════════════════╡
│ InvoiceNo   ┆ 10         ┆ 90             │
│ StockCode   ┆ 12         ┆ 88             │
│ Description ┆ 10         ┆ 90             │
│ Quantity    ┆ 13         ┆ 87             │
│ InvoiceDate ┆ 14         ┆ 86             │
│ UnitPrice   ┆ 8          ┆ 92             │
│ CustomerID  ┆ 9          ┆ 91             │
│ Country     ┆ 8          ┆ 92             │
└─────────────┴────────────┴────────────────┘
Ответ принят как подходящий

Давайте воспользуемся простым тестовым вводом

df = pl.DataFrame({
    "InvoiceNo": [1,2,3],
    "StockCode": [1,None,3],
    "Description": [None,None,6]
})

Чтобы получить желаемый результат, вы можете использовать

  • unpivot() для транспонирования DataFrame.
  • Кроме того, вам не обязательно вычислять оба значения: как только вы вычислили количество значений null, вы можете использовать len(df) - null_count для вычисления not_null_count.
(
    df
    .select(pl.all().is_null().sum())
    .unpivot(variable_name = "column", value_name = "null_count")
    .with_columns(not_null_count = len(df) - pl.col.null_count)
)

┌──────────────┬────────────┬────────────────┐
│ column       ┆ null_count ┆ not_null_count │
│ ---          ┆ ---        ┆ ---            │
│ str          ┆ u32        ┆ u32            │
╞══════════════╪════════════╪════════════════╡
│ InvoiceNo    ┆ 0          ┆ 3              │
│ StockCode    ┆ 1          ┆ 2              │
│ Description  ┆ 2          ┆ 1              │
└──────────────┴────────────┴────────────────┘

А если вы хотите, чтобы ваш результат имел форму без поворота (например, одна строка и несколько столбцов), вы можете использовать .name.suffix():

(
    df
    .with_columns(
        pl.all().is_null().sum().name.suffix("_is_null"),
        pl.all().is_not_null().sum().name.suffix("_is_not_null")
    )
)

┌───────────┬───────────┬──────────────┬───────────────┬───┬──────────────┬──────────────┬──────────────┬──────────────┐
│ InvoiceNo ┆ StockCode ┆ Description  ┆ InvoiceNo_is_ ┆ … ┆ Description  ┆ InvoiceNo_is ┆ StockCode_is ┆ Description  │
│ ---       ┆ ---       ┆ ---          ┆ null          ┆   ┆ _is_null     ┆ _not_null    ┆ _not_null    ┆ _is_not_null │
│ i64       ┆ i64       ┆ i64          ┆ ---           ┆   ┆ ---          ┆ ---          ┆ ---          ┆ ---          │
│           ┆           ┆              ┆ u32           ┆   ┆ u32          ┆ u32          ┆ u32          ┆ u32          │
╞═══════════╪═══════════╪══════════════╪═══════════════╪═══╪══════════════╪══════════════╪══════════════╪══════════════╡
│ 1         ┆ 1         ┆ null         ┆ 0             ┆ … ┆ 2            ┆ 3            ┆ 2            ┆ 1            │
│ 2         ┆ null      ┆ null         ┆ 0             ┆ … ┆ 2            ┆ 3            ┆ 2            ┆ 1            │
│ 3         ┆ 3         ┆ 6            ┆ 0             ┆ … ┆ 2            ┆ 3            ┆ 2            ┆ 1            │
└───────────┴───────────┴──────────────┴───────────────┴───┴──────────────┴──────────────┴──────────────┴──────────────┘

Есть ли особое преимущество в использовании unpivot вместо transpose, как я это сделал в своем ответе?

mozway 19.08.2024 08:27

честно говоря, не уверен, но в документации есть комментарий This is a very expensive operation. Perhaps you can do it differently.

Roman Pekar 19.08.2024 08:28

Хорошо, возможно, когда все типы столбцов разные, чего здесь быть не должно. Приятно знать. Дополнительный комментарий: благодаря вашему редактированию и добавлению name.suffix наши ответы становятся очень похожими.

mozway 19.08.2024 08:32

Да, я добавил это как дополнение, чтобы показать, почему первоначальная попытка ОП не удалась.

Roman Pekar 19.08.2024 08:34

Это довольно близко @RomanPekar, но что, если я попытаюсь получить, например, not_nulls() иmean()? Как я могу отменить поворот новых суффиксов, сохранив имена столбцов оригиналов?

Simon 19.08.2024 17:04

Другие вопросы по теме