Построчное агрегирование на основе ненулевых столбцов ⇐ Python

Программы на Python
Anonymous
Построчное агрегирование на основе ненулевых столбцов

Сообщение Anonymous »

Я столкнулся со сценарием, в котором у меня разреженный набор данных (для каждой строки одновременно заполняются только 4 столбца, остальные будут нулями). Для каждого префикса переменной будет 3 переменные (например, a_qty, a_height, ma_width), количество столбцов совершенно произвольное, поскольку новые префиксы могут быть добавлены в любое время.
Для примера, фрейм данных может выглядеть примерно так:
import polars as pl

df = pl.DataFrame(
{
"some_id": ["x", "y", "z"],
"a_qty": [1, 0, 0],
"a_height": [2, 0, 0],
"a_width": [3, 0, 0],
"b_qty": [0, 3, 0],
"b_height": [0, 5, 0],
"b_width": [0, 8, 0],
"c_qty": [0, 0, 10],
"c_height": [0, 0, 11],
"c_width": [0, 0, 12],
}
)
# prints
┌─────────┬───────┬──────────┬─────────┬───┬─────────┬───────┬──────────┬─────────┐
│ some_id ┆ a_qty ┆ a_height ┆ a_width ┆ … ┆ b_width ┆ c_qty ┆ c_height ┆ c_width │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 ┆ i64 ┆ ┆ i64 ┆ i64 ┆ i64 ┆ i64 │
╞═════════╪═══════╪══════════╪═════════╪═══╪═════════╪═══════╪══════════╪═════════╡
│ x ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 0 ┆ 0 ┆ 0 ┆ 0 │
│ y ┆ 0 ┆ 0 ┆ 0 ┆ … ┆ 8 ┆ 0 ┆ 0 ┆ 0 │
│ z ┆ 0 ┆ 0 ┆ 0 ┆ … ┆ 0 ┆ 10 ┆ 11 ┆ 12 │
└─────────┴───────┴──────────┴─────────┴───┴─────────┴───────┴──────────┴─────────┘

Я ищу способ сузить набор данных, уменьшив количество столбцов и избавившись от нулей для данной строки. Каждая строка целевого фрейма данных должна содержать:
  • qty: сумма столбцов, содержащих qty для данной строки (то же самое относится к ширине и высоте)
  • is_prod_* фиктивная переменная, имеющая значение 1 в зависимости от префикса ненулевых столбцов. Префиксы не смешиваются (только одна буква в строке)
df_target = pl.DataFrame(
{
"some_id": ["x", "y", "z"],
"height": [2, 5, 11],
"width": [3, 8, 12],
"qty": [1, 3, 10],
"is_prod_a": [1, 0, 0],
"is_prod_b": [0, 1, 0],
"is_prod_c": [0, 0, 1]
}
)
# prints
┌─────────┬────────┬───────┬─────┬────────┬────────┬────────┐
│ some_id ┆ height ┆ width ┆ qty ┆ prod_a ┆ prod_b ┆ prod_c │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 ┆ i64 ┆ i64 ┆ i64 ┆ i64 │
╞═════════╪════════╪═══════╪═════╪════════╪════════╪════════╡
│ x ┆ 2 ┆ 3 ┆ 1 ┆ 1 ┆ 0 ┆ 0 │
│ y ┆ 5 ┆ 8 ┆ 3 ┆ 0 ┆ 1 ┆ 0 │
│ z ┆ 11 ┆ 12 ┆ 10 ┆ 0 ┆ 0 ┆ 1 │
└─────────┴────────┴───────┴─────┴────────┴────────┴────────┘

Я пробовал группировать по номеру строки и суммировать переменные по типу:
width_cols = [col for col in df_test.columns if "width" in col],
height_cols = [col for col in df_test.columns if "height" in col]
qty_cols = [col for col in df_test.columns if "qty" in col]

(
df
.with_row_index()
.group_by("index")
.agg(
pl.col(*width_cols).sum().alias('width')
)
)

# DuplicateError: column with name 'width' has more than one occurrence

Это явно не работает, поскольку я пытаюсь создать дубликат столбца во второй строке. Какой самый элегантный способ добиться такого агрегирования?
Изменить 1
Можно получить суммы по строкам столбцов, используя pl. DataFrame.fold, который, похоже, помогает. Все еще не знаю, как создать фиктивный столбец с именем base на условии.
(
df_test
.with_columns(
pl.fold(0, lambda acc, s: acc + s, pl.col(*width_cols)).alias("width"),
pl.fold(0, lambda acc, s: acc + s, pl.col(*height_cols)).alias("height"),
pl.fold(0, lambda acc, s: acc + s, pl.col(*qty_cols)).alias("qty")
)
)


Подробнее здесь: https://stackoverflow.com/questions/770 ... ro-columns

Вернуться в «Python»