将含Struct列表的单行polars.DataFrame转换为DataFrame字典的优解
问题:将单行Polars DataFrame转换为列名映射DataFrame的字典
我有一个单行的Polars DataFrame(df),其结构如下:
df.schema >>> Schema([('S1', List(Struct({'S1': Float64, 'timestamp': Datetime(time_unit='us', time_zone=None)}))), ('S2', List(Struct({'S2': Float64, 'timestamp': Datetime(time_unit='us', time_zone=None)}))), ('S3', List(Struct({'S3': Float64, 'timestamp': Datetime(time_unit='us', time_zone=None)}))), ('CO', List(Struct({'CO': Float64, 'timestamp': Datetime(time_unit='us', time_zone=None)}))), ('RH', List(Struct({'RH': Float64, 'timestamp': Datetime(time_unit='us', time_zone=None)}))), ('TP', List(Struct({'TP': Float64, 'timestamp': Datetime(time_unit='us', time_zone=None)})))])
目标是将其转换为键为列名、值为Polars DataFrame的字典,当前使用的方法是:
{ c: pl.DataFrame(v.explode()).unnest(c) for c,v in df.to_dict().items() }
转换后得到的字典结构符合预期:
{'S1': Schema([('S1', Float64), ('timestamp', Datetime(time_unit='us', time_zone=None))]), 'S2': Schema([('S2', Float64), ('timestamp', Datetime(time_unit='us', time_zone=None))]), 'S3': Schema([('S3', Float64), ('timestamp', Datetime(time_unit='us', time_zone=None))]), 'CO': Schema([('CO', Float64), ('timestamp', Datetime(time_unit='us', time_zone=None))]), 'RH': Schema([('RH', Float64), ('timestamp', Datetime(time_unit='us', time_zone=None))]), 'TP': Schema([('TP', Float64), ('timestamp', Datetime(time_unit='us', time_zone=None))])}
由于原DataFrame中各列的列表长度不同,无法直接对整个df调用.explode()。下面提供两种更贴合Polars风格、更优雅的实现方式:
解法1:直接利用Polars列操作遍历处理
避免转换为字典,直接对每一列进行explode和unnest操作:
{ c: df.select(pl.col(c).explode()).unnest(c) for c in df.columns }
解法2:直接提取列表构造DataFrame(更高效)
因为原DataFrame是单行结构,每一列的唯一元素就是目标Struct列表,直接提取后构造DataFrame即可,无需额外的explode和unnest:
{ c: pl.DataFrame(df.get_column(c)[0]) for c in df.columns }
两种方法都能得到与原方法完全一致的结果,且更符合Polars的原生操作逻辑,避免了字典转换的额外开销。
示例数据
import datetime as dt import polars as pl df = pl.DataFrame({ 'S1': [[ {'S1': 102007.4 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 37)}, {'S1': 102007.45454545454 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 54)}, {'S1': 102005.83333333333 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 11)}, {'S1': 102000.07692307692 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 28)}, {'S1': 101996.0 , 'timestamp': dt.datetime(2024, 9, 4, 15, 0 , 1 )}, ]], 'S2': [[ {'S2': 50902.6 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 37)}, {'S2': 50904.09090909091 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 54)}, {'S2': 50904.833333333336 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 11)}, {'S2': 50903.0 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 28)}, ]], 'S3': [[ {'S3': 860903.6666666666 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 20)}, {'S3': 860899.4545454546 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 54)}, {'S3': 860862.5833333334 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 11)}, ]], 'CO': [[ {'CO': 639162.2 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 37)}, {'CO': 639161.2727272727 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 54)}, {'CO': 639159.4166666666 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 11)}, {'CO': 639167.5 , 'timestamp': dt.datetime(2024, 9, 4, 14, 59, 44)}, {'CO': 639163.2666666667 , 'timestamp': dt.datetime(2024, 9, 4, 15, 0, 1)}, ]], 'RH': [[ {'RH': 3655.3 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 37)}, {'RH': 3655.2727272727275 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 54)}, ]], 'TP': [[ {'TP': 2621.7 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 37)}, {'TP': 2621.818181818182 , 'timestamp': dt.datetime(2024, 9, 4, 14, 58, 54)}, ]], })
内容的提问来源于stack exchange,提问作者Hammad Ahmed
相关产品推荐
相关产品推荐

