如何在Polars的select/with_columns中直接将列转为Numpy数组?
问题:Polars中如何在with_columns/select语句内将表达式转为Numpy数组处理工作日
我需要把日期列转换为该日期之后的下一个工作日(日期本身是工作日则保持不变),打算用Numpy的busday_offset函数,但该函数需要接收Numpy数组作为第一个参数。尝试直接在表达式里调用to_numpy()时失败:
sales_orders.with_columns( [ pl.lit(np.busday_offset(pl.col('creation_date').to_numpy(), 0, roll='forward')) ] )
报错:AttributeError: 'Expr' object has no attribute 'to_numpy'
用原表的get_column方法可以临时解决,但这种写法不够优雅,而且无法在链式with_columns中引用新生成的列:
sales_orders.with_columns( [ pl.lit(np.busday_offset(sales_orders.get_column('creation_date').to_numpy(), 0, roll='forward')).alias('order_acknowledgement_date') ] ).with_columns( [ pl.lit(np.busday_offset(sales_orders.get_column('order_acknowledgement_date'), 2, roll='forward')).alias('ship_due_date') ] )
报错:ColumnNotFoundError: order_acknowledgement_date
请问如何在select/with_columns语句中,无需直接引用原表,将pl.col('creation_date')转换为Numpy数组?
解决方案
使用Polars的map_batches方法,它允许在表达式上下文内将列数据转为Numpy数组进行处理,既不用直接依赖原表对象,也支持链式调用新生成的列:
基础用法(生成下一个工作日)
import polars as pl import numpy as np sales_orders = sales_orders.with_columns( pl.col('creation_date') .map_batches(lambda chunk: np.busday_offset(chunk.to_numpy(), 0, roll='forward')) .alias('next_business_day') )
链式调用(生成依赖新列的日期)
sales_orders = sales_orders.with_columns( pl.col('creation_date') .map_batches(lambda chunk: np.busday_offset(chunk.to_numpy(), 0, roll='forward')) .alias('order_acknowledgement_date') ).with_columns( pl.col('order_acknowledgement_date') .map_batches(lambda chunk: np.busday_offset(chunk.to_numpy(), 2, roll='forward')) .alias('ship_due_date') )
原理说明
map_batches会将列的ChunkedArray对象传递给lambda函数,而ChunkedArray支持调用to_numpy()转为Numpy数组,刚好适配np.busday_offset的参数要求。同时,整个操作在Polars的表达式链中完成,后续的with_columns可以直接引用前面生成的新列,避免了找不到列的问题。
内容的提问来源于stack exchange,提问作者Viktor Crettenand
相关产品推荐
相关产品推荐

