Eu tenho esse código, que divide uma product
coluna em uma lista e depois a usa explode
para expandi-la:
import polars as pl
import datetime as dt
from dateutil.relativedelta import relativedelta
def get_3_month_splits(product: str) -> list[str]:
front, start_dt, total_m = product.rsplit('.', 2)
start_dt = dt.datetime.strptime(start_dt, '%Y%m')
total_m = int(total_m)
return [f'{front}.{(start_dt+relativedelta(months=m)).strftime("%Y%m")}.3' for m in range(0, total_m, 3)]
df = pl.DataFrame({
'product': ['CHECK.GB.202403.12', 'CHECK.DE.202506.6', 'CASH.US.202509.12'],
'qty': [10, -20, 50],
'price_paid': [1400, -3300, 900],
})
print(df.with_columns(pl.col('product').map_elements(get_3_month_splits, return_dtype=pl.List(str))).explode('product'))
Isso atualmente dá
shape: (10, 3)
┌───────────────────┬─────┬────────────┐
│ product ┆ qty ┆ price_paid │
│ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 │
╞═══════════════════╪═════╪════════════╡
│ CHECK.GB.202403.3 ┆ 10 ┆ 1400 │
│ CHECK.GB.202406.3 ┆ 10 ┆ 1400 │
│ CHECK.GB.202409.3 ┆ 10 ┆ 1400 │
│ CHECK.GB.202412.3 ┆ 10 ┆ 1400 │
│ CHECK.DE.202506.3 ┆ -20 ┆ -3300 │
│ CHECK.DE.202509.3 ┆ -20 ┆ -3300 │
│ CASH.US.202509.3 ┆ 50 ┆ 900 │
│ CASH.US.202512.3 ┆ 50 ┆ 900 │
│ CASH.US.202603.3 ┆ 50 ┆ 900 │
│ CASH.US.202606.3 ┆ 50 ┆ 900 │
└───────────────────┴─────┴────────────┘
No entanto, quero manter o total price paid
o mesmo. Então, depois de dividir as linhas em várias "subcategorias", quero mudar a tabela para isto:
shape: (10, 3)
┌───────────────────┬─────┬────────────┐
│ product ┆ qty ┆ price_paid │
│ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 │
╞═══════════════════╪═════╪════════════╡
│ CHECK.GB.202403.3 ┆ 10 ┆ 1400 │
│ CHECK.GB.202406.3 ┆ 10 ┆ 0 │
│ CHECK.GB.202409.3 ┆ 10 ┆ 0 │
│ CHECK.GB.202412.3 ┆ 10 ┆ 0 │
│ CHECK.DE.202506.3 ┆ -20 ┆ -3300 │
│ CHECK.DE.202509.3 ┆ -20 ┆ 0 │
│ CASH.US.202509.3 ┆ 50 ┆ 900 │
│ CASH.US.202512.3 ┆ 50 ┆ 0 │
│ CASH.US.202603.3 ┆ 50 ┆ 0 │
│ CASH.US.202606.3 ┆ 50 ┆ 0 │
└───────────────────┴─────┴────────────┘
ou seja, mantendo apenas o price_paid
na primeira linha expandida. Então meu preço total pago permanece o mesmo. O qty
está tudo bem em ficar do jeito que está.
Eu tentei eg with_columns(price_arr=pl.col('product').cast(pl.List(pl.Float64)))
mas não consegui adicionar nada ao primeiro elemento da lista. Ou with_columns(price_arr=pl.col(['product', 'price_paid']).map_elements(price_func))
mas não pareceu possível usar map_elements
on pl.col([...])
.
Concatene o número apropriado de
0
s finaisprice_paid
antes de chamar.explode()
ambosproduct
eprice_paid
ao mesmo tempo:Saída:
você pode usar
is_first_distinct()
ewhen/then
:Você também pode evitar o uso
map_elements()
e usar expressões polares puras (é um pouco difícil, mas você entendeu a ideia):