Для примера, фрейм данных может выглядеть примерно так:
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 в зависимости от префикса ненулевых столбцов. Префиксы не смешиваются (только одна буква в строке)
{
"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