Polars中按行计算分位数:当前实现方式是否为推荐方案?
行级计算分位数的Polars实现方式探讨
我有一些Polars DataFrame,需要计算行级统计量。部分统计量有专用的
.list.func方法(例如list.mean),但对于没有专用方法的统计量,我认为必须使用list.eval。
示例数据如下:import numpy as np import polars as pl df = pl.DataFrame({ 'a': [1,10,1,.1,.1, np.NAN], 'b': [2, 8,1,.2, np.NAN,np.NAN], 'c': [3, 6,2,.3,.2, np.NAN], 'd': [4, 4,3,.4, np.NAN,np.NAN], 'e': [5, 2,3,.5,.3, np.NAN], }, strict=False)我写出了如下表达式:
df.select( pl.concat_list( pl.all().fill_nan(None) ) .list.eval(pl.element().quantile(0.25)) .explode() .alias('q1') )
list.eval返回的是列表,因此需要调用.explode将单元素列表转为单个值,再用.alias重命名列。请问这是按行计算分位数的推荐方式吗?
你的实现方式是可行的,但有更简洁的优化方向:
避免
explode操作:在list.eval内部直接提取结果值,无需事后展开。可以用.list.first()或者索引[0]来获取单元素列表里的值:df.select( pl.concat_list(pl.all().fill_nan(None)) .list.eval(pl.element().quantile(0.25)).list.first() .alias('q1') )使用
row()方法(Polars 0.19.0+):这个API是专门为行级计算设计的,语法更直观,不用手动拼接列表:df.select( pl.row(pl.all().fill_nan(None)).map_elements( lambda x: np.nanquantile(x, 0.25) if any(v is not None for v in x) else None ).alias('q1') )这里用
np.nanquantile是因为它能自动忽略None(Polars会将None转换为numpy的nan),同时处理全空行时返回None,保证结果的一致性。
总的来说,list.eval确实是处理这类无专用list方法统计量的常规手段,而row()方法是Polars后续推出的更友好的行级计算方案,你可以根据自己使用的Polars版本和实际需求选择。
内容的提问来源于stack exchange,提问作者Steve Lorimer
相关产品推荐
相关产品推荐

