我目前正在从 pandas“转换”为 Polars,因为我真的很喜欢这个 api。这个问题是我之前的问题的一个更普遍的问题(请参阅此处)
我有以下数据框
# Dummy data
df = pl.DataFrame({
"Buy_Signal": [1, 0, 1, 0, 1, 0, 0],
"Returns": [0.01, 0.02, 0.03, 0.02, 0.01, 0.00, -0.01],
})
我想最终Returns
对不同间隔的列条件进行聚合 - 由 column 给出Buy_Signal
。在上述情况下,长度是从每个 1 到数据帧的末尾。因此,生成的数据框应如下所示
| group | Returns |
|------: |--------: |
| u32 | f64 |
| 1 | 0.01 |
| 1 | 0.02 |
| 1 | 0.03 |
| 1 | 0.02 |
| 1 | 0.01 |
| 1 | 0.0 |
| 1 | -0.01 |
| 2 | 0.03 |
| 2 | 0.02 |
| 2 | 0.01 |
| 2 | 0.0 |
| 2 | -0.01 |
| 3 | 0.01 |
| 3 | 0.0 |
| 3 | -0.01 |
作为我上一个问题的答案发布的一种方法如下:
# Build overlapping group index
idx = df.select(index=
pl.when(pl.col("Buy_Signal") == 1)
.then(pl.int_ranges(pl.int_range(pl.len()), pl.len() ))
).explode(pl.col("index")).drop_nulls().cast(pl.UInt32)
# Join index with original data
df = (df.with_row_index()
.join(idx, on="index")
.with_columns(group = (pl.col("index") == pl.col("index").max())
.shift().cum_sum().backward_fill() + 1)
.select(["group", "Returns"])
)
df
问:这个问题还有其他好的解决办法吗?
我所说的“好”是指(i)可读和/或(ii)快速。
我的实际问题包含更大的数据集。
谢谢
为了完整起见,这里有一个不依赖实验功能的替代解决方案。
输出。
我认为这是使用 的一个很好的案例
cumulative_eval()
。乍一看,您需要对 DataFrame 进行 2 次传递。首先,您需要计算
cum_sum
以获得正确的分组:请注意,目前我们的 DataFrame 是用 排序的
descending=True
,这很重要,因为我们希望我们的列表从最大组到最小组聚合。现在
cumulative_eval()
,连同implode()
:您可以看到结果与您的预期相符。但是,您必须小心性能,因为
cumulative_eval
文档中有注释:只是添加一些更多信息,因为我认为问题标题是基于我之前的糟糕措辞:
我找到了问题的现有定义(这可能是问题的更好标题?)
Polars 相当于 SQL 的
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
窗口框架。例如使用DuckDB来演示: