Eu tenho o seguinte código.
import polars as pl
class Summary:
def __init__(self, value: float, origin: str):
self.value = value
self.origin = origin
def __repr__(self) -> str:
return f'Summary({self.value},{self.origin})'
def __mul__(self, x: float | int) -> 'Summary':
return Summary(self.value * x, self.origin)
def __rmul__(self, x: float | int) -> 'Summary':
return self * x
mapping = {
'CASH': Summary( 1, 'E'),
'ITEM': Summary(-9, 'A'),
'CHECK': Summary(46, 'A'),
}
df = pl.DataFrame({'quantity': [7, 4, 10], 'type': mapping.keys(), 'summary': mapping.values()})
O dataframe df
tem a seguinte aparência.
shape: (3, 3)
┌──────────┬───────┬───────────────┐
│ quantity ┆ type ┆ summary │
│ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ object │
╞══════════╪═══════╪═══════════════╡
│ 7 ┆ CASH ┆ Summary(1,E) │
│ 4 ┆ ITEM ┆ Summary(-9,A) │
│ 10 ┆ CHECK ┆ Summary(46,A) │
└──────────┴───────┴───────────────┘
Especialmente, a summary
coluna contém um Summary
objeto de classe, que suporta multiplicação. Agora, gostaria de multiplicar esta coluna pela quantity
coluna.
No entanto, a abordagem ingénua levanta um erro.
df.with_columns(pl.col('quantity').mul(pl.col('summary')).alias('qty_summary'))
SchemaError: failed to determine supertype of i64 and object
Existe uma maneira de multiplicar essas colunas?
Lembre-se de que o Polars foi projetado para que os cálculos sejam executados em Rust, não em Python, onde é 1000x mais rápido. Se você deseja executar operações Python, você perde muitos benefícios de usar Polars em primeiro lugar.
Mas, felizmente, o Polars tem um recurso muito interessante que é relevante aqui, que é o processamento “nativo” de arquivos
dataclasses
.Porque
Summary
é umdataclass
, você 1. não precisa__init__
de e__repr__
(eles vêm de graça) e 2. não precisa fazer nada especial para que os Polars os estruturem.Agora você pode simplesmente fazer operações regulares de estrutura Polars:
Você mencionou nos comentários que gostaria de poder multiplicar determinados campos da
Summary
coluna por outra coluna.Talvez como sugestão você possa armazenar seus dados como uma estrutura:
E defina separadamente uma lista de campos que você deseja que sejam afetados. Você pode usar
with_fields()
para multiplicar alguns dos campos da estrutura: