You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于整洁Polars DataFrame计算横截面排名及优化问询

多证券横截面排名的Polars实现优化

问题1:将ranks逆透视为整洁格式DataFrame

你可以通过两次逆透视(melt)+ 合并的方式实现,先处理收益列,再拆分排名列表并处理,最后将两者按日期和标的关联:

# 第一步:将宽表的return列逆透视成长表
melted_returns = ranks.melt(
    id_vars="date",
    value_name="return",
    variable_name="symbol"
)

# 第二步:把rank列表转换为结构体后展开,再逆透视
rank_struct = ranks.select(
    "date",
    pl.col("rank").list.to_struct(fields=ranks.columns[1:-1])
).unnest("rank")

melted_ranks = rank_struct.melt(
    id_vars="date",
    value_name="rank",
    variable_name="symbol"
)

# 第三步:合并收益和排名数据
final_df = melted_returns.join(melted_ranks, on=["date", "symbol"]).sort(["date", "symbol"])
print(final_df)

输出结果:

shape: (18, 4)
┌────────────┬─────────┬──────────┬──────┐
│ date       ┆ symbol  ┆ return   ┆ rank │
│ ---        ┆ ---     ┆ ---      ┆ ---  │
│ str        ┆ str     ┆ f64      ┆ u8   │
╞════════════╪═════════╪══════════╪══════╡
│ 2023-12-30 ┆ symbol1 ┆ null     ┆ null │
│ 2023-12-30 ┆ symbol2 ┆ null     ┆ null │
│ 2023-12-30 ┆ symbol3 ┆ null     ┆ null │
│ 2023-12-31 ┆ symbol1 ┆ null     ┆ null │
│ 2023-12-31 ┆ symbol2 ┆ null     ┆ null │
│ …          ┆ …       ┆ …        ┆ …    │
│ 2024-01-05 ┆ symbol2 ┆ 0.095238 ┆ 1    │
│ 2024-01-05 ┆ symbol3 ┆ 0.0625   ┆ 3    │
│ 2024-01-06 ┆ symbol1 ┆ 0.086957 ┆ 2    │
│ 2024-01-06 ┆ symbol2 ┆ 0.090909 ┆ 1    │
│ 2024-01-06 ┆ symbol3 ┆ null     ┆ null │
└────────────┴─────────┴──────────┴──────┘

问题2:无需透视,直接在长格式DataFrame上高效计算

完全不需要先透视,Polars支持直接按date分组计算横截面排名,这是更高效的方案(尤其适合百万级数据):

result = df.with_columns(
    # 先计算每个标的的周期收益
    pl.col("price").pct_change(n=2).over("symbol").alias("return")
).with_columns(
    # 按日期分组,对收益降序排名(自动忽略null值)
    pl.col("return")
    .rank(descending=True, method="ordinal")
    .over("date")
    .cast(pl.UInt8)
    .alias("rank")
).sort(["date", "symbol"])

print(result)

输出结果(和问题1的最终结果逻辑一致,且保留原数据的所有行):

shape: (16, 5)
┌─────────┬────────────┬───────┬──────────┬──────┐
│ symbol  ┆ date       ┆ price ┆ return   ┆ rank │
│ ---     ┆ ---        ┆ ---   ┆ ---      ┆ ---  │
│ str     ┆ str        ┆ i64   ┆ f64      ┆ u8   │
╞═════════╪════════════╪═══════╪══════════╪══════╡
│ symbol1 ┆ 2023-12-30 ┆ 100   ┆ null     ┆ null │
│ symbol2 ┆ 2023-12-30 ┆ 200   ┆ null     ┆ null │
│ symbol3 ┆ 2023-12-30 ┆ 3000  ┆ null     ┆ null │
│ symbol1 ┆ 2023-12-31 ┆ 105   ┆ null     ┆ null │
│ symbol3 ┆ 2023-12-31 ┆ 3100  ┆ null     ┆ null │
│ …       ┆ …          ┆ …     ┆ …        ┆ …    │
│ symbol1 ┆ 2024-01-05 ┆ 120   ┆ 0.090909 ┆ 2    │
│ symbol2 ┆ 2024-01-05 ┆ 230   ┆ 0.095238 ┆ 1    │
│ symbol3 ┆ 2024-01-05 ┆ 3400  ┆ 0.0625   ┆ 3    │
│ symbol1 ┆ 2024-01-06 ┆ 125   ┆ 0.086957 ┆ 2    │
│ symbol2 ┆ 2024-01-06 ┆ 240   ┆ 0.090909 ┆ 1    │
└─────────┴────────────┴───────┴──────────┴──────┘

性能说明

这种直接在长表上用over("date")分组排名的方式,避免了透视/逆透视带来的数据结构转换开销,Polars的矢量化分组操作可以高效处理百万级行数据,远优于先透视再处理的方案。

内容的提问来源于stack exchange,提问作者Andi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 00:20:10