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

Python-Polars中结构体列的跨字段组合计算优化方案咨询

Python-Polars中结构体列的跨字段组合计算优化方案咨询

我明白你现在的困扰——用map_elements虽然能实现需求,但不仅效率不高,还要手动指定返回类型,确实不够灵活。下面我给你一个纯Polars表达式的方案,完全不用map_elements,而且是向量化操作,性能更好:

先回顾你的输入数据:

import polars as pl
from itertools import product

df = pl.DataFrame({
    'cases': ['case_1', 'case_2'],
    'value_1': [
        {'value_decimal': 22.5, 'value_decimal_lb': 22.0, 'value_decimal_ub': 23.0},
        {'value_decimal': 23.0, 'value_decimal_lb': 22.5, 'value_decimal_ub': 23.5}
    ],
    'value_2': [
        {'value_decimal': 5.0, 'value_decimal_lb': 5.0, 'value_decimal_ub': 5.0},
        {'value_decimal': 5.0, 'value_decimal_lb': 6.0, 'value_decimal_ub': 5.0}
    ]
})

你的需求是新增一个result列,存储每行中两个结构体的value_decimal_lb和value_decimal_ub值的所有跨列组合。


优化方案:纯向量化表达式实现

下面这个方案全程用Polars内置表达式完成,没有行级遍历的map_elements,性能更优且无需手动指定返回类型:

df_result = df.with_columns(
    # 第一步:提取每个结构体的lb和ub,转为数组列
    v1_arr=pl.array([
        pl.col('value_1').struct.field('value_decimal_lb'),
        pl.col('value_1').struct.field('value_decimal_ub')
    ]),
    v2_arr=pl.array([
        pl.col('value_2').struct.field('value_decimal_lb'),
        pl.col('value_2').struct.field('value_decimal_ub')
    ])
).with_columns(
    # 第二步:生成笛卡尔积所需的重复/平铺数组
    v1_repeated=pl.col('v1_arr').repeat(pl.col('v2_arr').arr.lengths()).arr.flatten(),
    v2_tiled=pl.col('v2_arr').arr.tile(pl.col('v1_arr').arr.lengths()).arr.flatten()
).with_columns(
    # 第三步:将两个数组合并为嵌套列表的结果列
    result=pl.struct(pl.col('v1_repeated'), pl.col('v2_tiled')).arr.to_list()
).drop('v1_arr', 'v2_arr', 'v1_repeated', 'v2_tiled')

print(df_result)

执行后得到的结果和你的期望完全一致:

shape: (2, 4)
┌────────┬──────────────────┬───────────────┬─────────────────────────────────┐
│ cases  ┆ value_1          ┆ value_2       ┆ result                          │
│ ---    ┆ ---              ┆ ---           ┆ ---                             │
│ str    ┆ struct[3]        ┆ struct[3]     ┆ list[list[f64]]                 │
╞════════╪══════════════════╪═══════════════╪═════════════════════════════════╡
│ case_1 ┆ {22.5,22.0,23.0} ┆ {5.0,5.0,5.0} ┆ [[22.0, 5.0], [22.0, 5.0], … [… │
│ case_2 ┆ {23.0,22.5,23.5} ┆ {5.0,6.0,5.0} ┆ [[22.5, 5.0], [22.5, 6.0], … [… │
└────────┴──────────────────┴───────────────┴─────────────────────────────────┘

方案细节解释

  1. 提取结构体字段为数组:用pl.array直接把每个结构体的lb和ub字段组合成数组列,这一步是完全向量化的,比map_elements遍历每行快得多。
  2. 生成笛卡尔积数组:
    • repeat方法会把第一个数组的每个元素重复第二个数组的长度次,比如[a,b]重复2次变成[a,a,b,b]
    • tile方法会把第二个数组整体重复第一个数组的长度次,比如[x,y]平铺2次变成[x,y,x,y]
    • 再用arr.flatten把嵌套数组展开成一维数组,这样两个数组的对应元素就是笛卡尔积的组合对
  3. 合并为嵌套列表:用pl.struct把两个一维数组的元素配对,再通过arr.to_list转成嵌套列表,就是我们需要的结果。

这个方案不仅不需要手动指定return_dtype(Polars会自动推断类型),而且因为全程是向量化操作,处理大数据集时的性能会比map_elements好很多。如果以后需要扩展到更多结构体列,只需要重复第一步的数组提取,然后调整笛卡尔积的重复/平铺逻辑即可,扩展性也很强。

备注:内容来源于stack exchange,提问作者yz_jc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:57:58