如何以并行方式用单元格值字典更新Polars DataFrame单元格?
高效更新Polars DataFrame指定单元格的方法
你的循环逐单元格更新的方式效率很低,核心问题是每次调用with_columns都会生成新的DataFrame副本,而且逐行判断的逻辑完全浪费了Polars的向量化并行能力。下面是两种更高效的实现方案:
方案一:长格式转换+关联更新(最优)
这种方法通过将原DataFrame和调整字典都转换为长格式,利用Polars的join和向量化计算批量完成更新,能充分发挥Polars的并行处理优势:
- 将调整字典转换为结构化DataFrame
adjust_df = pl.DataFrame( [(row_id, col, val) for (row_id, col), val in adjustments.items()], schema=["row_id", "column", "adjust_val"] )
- 原DataFrame转长格式,关联调整值后计算新值
# 把宽表转成"row_id-列名-原值"的长格式 melted = count_table.melt(id_vars="row_id", value_name="original_val") # 关联调整值,仅对有调整的单元格计算新值 updated_melted = melted.join(adjust_df, on=["row_id", "column"], how="left").with_columns( pl.when(pl.col("adjust_val").is_not_null()) .then(pl.col("original_val") + pl.col("adjust_val")) .otherwise(pl.col("original_val")) .alias("updated_val") )
- 转回宽格式,恢复原DataFrame的结构
# 把长格式转回宽格式,保持原列顺序 count_table_updated = updated_melted.pivot( index="row_id", columns="column", values="updated_val" ).select(["row_id"] + columns)
这个方案的核心优势:
- 全程使用Polars的向量化操作,彻底避免循环开销
- 仅需几次批量操作,大幅减少DataFrame复制次数
- 数据量越大,相比循环方法的性能提升越显著
方案二:使用join+update(适合小量调整)
如果调整的单元格数量不多,可以直接构造匹配原结构的更新数据,用join批量更新:
# 构造按row_id分组的调整字典 row_adjustments = {} for (row_id, col), val in adjustments.items(): row_adjustments.setdefault(row_id, {})[col] = val # 转换为Polars可识别的更新DataFrame update_data = pl.DataFrame([ {"row_id": row_id, **cols} for row_id, cols in row_adjustments.items() ]) # 关联后批量更新各列 count_table_updated = count_table.join(update_data, on="row_id", how="left").with_columns( [ pl.when(pl.col(f"{col}_right").is_not_null()) .then(pl.col(col) + pl.col(f"{col}_right")) .otherwise(pl.col(col)) .alias(col) for col in columns ] ).drop([f"{col}_right" for col in columns])
这个方法比循环高效,但当调整的单元格数量较多时,灵活性和性能不如方案一。
内容的提问来源于stack exchange,提问作者Bob La
相关产品推荐
相关产品推荐

