如何用Polars实现Numpy数组与Datetime的多LazyFrame合并及相关问题
Pandas转Polars:内存创建、广播与重复列名处理
1. 尽量不复制数据从内存创建Polars DataFrame
Polars基于Arrow内存模型,默认会尽可能减少数据复制:
- 使用
pl.DataFrame.from_dict()时,传入numpy数组或Python原生序列(如列表),若类型匹配Arrow原生类型(如np.int64、np.float64、np.datetime64),Polars会尝试零拷贝导入;仅当类型不兼容时才触发必要转换(这类场景比Pandas少)。 - 直接导入numpy数组用
pl.from_numpy(),对支持的类型属于纯零拷贝操作。 - 处理datetime类型时,直接传入
datetime.datetime对象列表或np.datetime64数组即可,Polars无需额外复制就能解析为pl.Datetime类型。
示例:
import polars as pl import numpy as np from datetime import datetime # 零拷贝导入numpy数组 arr = np.random.rand(1000, 2) df = pl.from_numpy(arr, columns=["col1", "col2"]) # 混合类型的低拷贝创建 data = { "values": np.random.randint(0, 100, 1000), "timestamps": np.array([datetime.now()] * 1000, dtype="datetime64[ns]") } df = pl.DataFrame(data)
2. 处理广播(如固定datetime值的列)
Polars的广播逻辑比Pandas更简洁,无需手动将标量扩展为匹配行数的序列,直接用pl.lit()传入标量即可自动广播到全量行:
- 添加单个datetime标量作为列:
df = df.with_columns(pl.lit(datetime(2024, 1, 1)).alias("C")) - 无需像Pandas那样用
np.repeat或pd.Series([val]*len(df))生成多行列,Polars会自动处理维度匹配。
示例:
# 给已有DataFrame添加两个广播的datetime列 df = df.with_columns( pl.lit(datetime(2024, 1, 1)).alias("C"), pl.lit(datetime(2024, 12, 31)).alias("D") )
3. 处理重复列名
Polars默认允许重复列名,但操作时需注意区分规则:
- 创建阶段:若传入的列名列表存在重复(如
names=["a", "a"]),Polars会直接保留重复名称,不会自动修改。 - 查询/操作阶段:若要选择重复列,不能直接用
pl.col("a")(会选中所有名为a的列),可通过位置索引(如pl.col(0))或提前重命名来区分。 - 合并阶段:若合并的DataFrame存在重复列名,Polars会保留所有重复列,不会自动添加后缀。可在合并前用
rename()重命名,或合并后用suffix()给重复列批量加后缀。
示例:
# 创建带重复列名的DataFrame df_dup = pl.DataFrame( [[1, 2], [3, 4]], columns=["val", "val"] ) # 选择第一个"val"列 first_val = df_dup.select(pl.col("val").first()) # 合并时处理重复列 df1 = pl.DataFrame({"val": [1,2]}) df2 = pl.DataFrame({"val": [3,4]}) merged = df1.hstack(df2.rename({"val": "val_2"}))
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

