我有以下代码。
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()})
数据框df
如下所示。
shape: (3, 3)
┌──────────┬───────┬───────────────┐
│ quantity ┆ type ┆ summary │
│ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ object │
╞══════════╪═══════╪═══════════════╡
│ 7 ┆ CASH ┆ Summary(1,E) │
│ 4 ┆ ITEM ┆ Summary(-9,A) │
│ 10 ┆ CHECK ┆ Summary(46,A) │
└──────────┴───────┴───────────────┘
特别地,summary
列中包含一个Summary
类对象,该类对象支持乘法。现在,我想将该列与该quantity
列相乘。
然而,这种简单的方法会引发错误。
df.with_columns(pl.col('quantity').mul(pl.col('summary')).alias('qty_summary'))
SchemaError: failed to determine supertype of i64 and object
有没有办法将这些列相乘?
请记住,Polars 的设计目的是让计算在 Rust 而不是 Python 中运行,后者的速度要快 1000 倍。如果您想要运行 Python 操作,那么您首先就会失去使用 Polars 的很多好处。
但值得庆幸的是,Polars 确实有一个与此相关的非常好的功能,那就是“原生”处理
dataclasses
。因为
Summary
是dataclass
,所以您 1. 不需要__init__
和__repr__
(它们是免费的),并且 2. 不需要对 Polars 进行任何特殊操作来构造它们。现在您可以执行常规的 Polars 结构操作:
您在评论中提到,您希望能够将
Summary
列的某些字段与另一列相乘。也许你可以建议你将数据存储为结构体:
只需单独定义您想要受影响的字段列表即可。您可以使用它
with_fields()
来乘以结构中的某些字段: