Используйте поляры «когда-то-иначе» одновременно в нескольких выходных столбцах

Предположим, у меня есть этот фрейм данных

import polars as pl

df = pl.DataFrame({
    'item':         ['CASH', 'CHECK', 'DEBT', 'CHECK', 'CREDIT', 'CASH'],
    'quantity':     [100, -20, 0, 10, 0, 0],
    'value':        [99, 47, None, 90, None, 120],
    'value_other':  [97, 57, None, 91, None, 110],
    'value_other2': [94, 37, None, 93, None, 115],
})
┌────────┬──────────┬───────┬─────────────┬──────────────┐
│ item   ┆ quantity ┆ value ┆ value_other ┆ value_other2 │
│ ---    ┆ ---      ┆ ---   ┆ ---         ┆ ---          │
│ str    ┆ i64      ┆ i64   ┆ i64         ┆ i64          │
╞════════╪══════════╪═══════╪═════════════╪══════════════╡
│ CASH   ┆ 100      ┆ 99    ┆ 97          ┆ 94           │
│ CHECK  ┆ -20      ┆ 47    ┆ 57          ┆ 37           │
│ DEBT   ┆ 0        ┆ null  ┆ null        ┆ null         │
│ CHECK  ┆ 10       ┆ 90    ┆ 91          ┆ 93           │
│ CREDIT ┆ 0        ┆ null  ┆ null        ┆ null         │
│ CASH   ┆ 0        ┆ 120   ┆ 110         ┆ 115          │
└────────┴──────────┴───────┴─────────────┴──────────────┘

Теперь я хочу установить для всех столбцов значений значение 0 для всех строк, где value is null и quantity == 0.

Прямо сейчас у меня есть это решение

cols = ['value', 'value_other', 'value_other2']
df   = df.with_columns([
    pl.when(pl.col('value').is_null() & (pl.col('quantity') == 0))
    .then(0)
    .otherwise(pl.col(col))
    .alias(col)
    for col in cols
])

что правильно дает

┌────────┬──────────┬───────┬─────────────┬──────────────┐
│ item   ┆ quantity ┆ value ┆ value_other ┆ value_other2 │
│ ---    ┆ ---      ┆ ---   ┆ ---         ┆ ---          │
│ str    ┆ i64      ┆ i64   ┆ i64         ┆ i64          │
╞════════╪══════════╪═══════╪═════════════╪══════════════╡
│ CASH   ┆ 100      ┆ 99    ┆ 97          ┆ 94           │
│ CHECK  ┆ -20      ┆ 47    ┆ 57          ┆ 37           │
│ DEBT   ┆ 0        ┆ 0     ┆ 0           ┆ 0            │
│ CHECK  ┆ 10       ┆ 90    ┆ 91          ┆ 93           │
│ CREDIT ┆ 0        ┆ 0     ┆ 0           ┆ 0            │
│ CASH   ┆ 0        ┆ 120   ┆ 110         ┆ 115          │
└────────┴──────────┴───────┴─────────────┴──────────────┘

Однако я считаю, что это очень неэффективно, поскольку мое условие when выполняется для каждого столбца значений. Есть ли способ добиться этого, используя только полярные внутренние функции и без встроенного цикла for?

stackoverflow.com/questions/75211934
jqurious 02.08.2024 08:36
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
7
1
149
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Примените условие ко всем столбцам одновременно. Также замените alias на name.keep:

cols = ['value', 'value_other', 'value_other2']

(df.with_columns(
    pl.when(pl.col('value').is_null() & (pl.col('quantity') == 0))
    .then(0)
    .otherwise(pl.col(cols))
    .name.keep()
))

Выход:

┌────────┬──────────┬───────┬─────────────┬──────────────┐
│ item   ┆ quantity ┆ value ┆ value_other ┆ value_other2 │
│ ---    ┆ ---      ┆ ---   ┆ ---         ┆ ---          │
│ str    ┆ i64      ┆ i64   ┆ i64         ┆ i64          │
╞════════╪══════════╪═══════╪═════════════╪══════════════╡
│ CASH   ┆ 100      ┆ 99    ┆ 97          ┆ 94           │
│ CHECK  ┆ -20      ┆ 47    ┆ 57          ┆ 37           │
│ DEBT   ┆ 0        ┆ 0     ┆ 0           ┆ 0            │
│ CHECK  ┆ 10       ┆ 90    ┆ 91          ┆ 93           │
│ CREDIT ┆ 0        ┆ 0     ┆ 0           ┆ 0            │
│ CASH   ┆ 0        ┆ 120   ┆ 110         ┆ 115          │
└────────┴──────────┴───────┴─────────────┴──────────────┘
Ответ принят как подходящий

Вы можете передать список имен столбцов в pl.col() и , когда\то\иначе принимает Expr, который может содержать несколько столбцов.

cols = ['value', 'value_other', 'value_other2']

df.with_columns(
    pl
    .when((pl.col.quantity != 0) | pl.col.value.is_not_null())
    .then(pl.col(cols))
    .otherwise(0)
)

# or

df.with_columns(
    pl
    .when(pl.col.quantity != 0).then(pl.col(cols))
    .when(pl.col.value.is_not_null()).then(pl.col(cols))
    .otherwise(0)
)
shape: (6, 5)
┌────────┬──────────┬───────┬─────────────┬──────────────┐
│ item   ┆ quantity ┆ value ┆ value_other ┆ value_other2 │
│ ---    ┆ ---      ┆ ---   ┆ ---         ┆ ---          │
│ str    ┆ i64      ┆ i64   ┆ i64         ┆ i64          │
╞════════╪══════════╪═══════╪═════════════╪══════════════╡
│ CASH   ┆ 100      ┆ 99    ┆ 97          ┆ 94           │
│ CHECK  ┆ -20      ┆ 47    ┆ 57          ┆ 37           │
│ DEBT   ┆ 0        ┆ 0     ┆ 0           ┆ 0            │
│ CHECK  ┆ 10       ┆ 90    ┆ 91          ┆ 93           │
│ CREDIT ┆ 0        ┆ 0     ┆ 0           ┆ 0            │
│ CASH   ┆ 0        ┆ 120   ┆ 110         ┆ 115          │
└────────┴──────────┴───────┴─────────────┴──────────────┘

я хотел явно указать условия для value и quantity, а затем установить для всех столбцов значений значение 0. Есть что-то вроде df.with_columns(pl.col('value').is_null() & (pl.col('quantity') == 0)).then(pl.col(cols).fill(0)).otherwise(pl.col(cols)))?

Phil-ZXX 01.08.2024 19:42

Ах, теперь я вижу, я неправильно прочитал требования. Смотрите обновленный ответ.

Roman Pekar 01.08.2024 21:39

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