Polars 中使用 join_asof 实现分段映射与差值计算

发布时间 - 2026-01-04 00:00:00    点击率:

本文介绍如何在 polars 中高效生成新列 `baz`:对 dataframe 的 `bar` 列中每个值,从预排序列表 `points` 中查找**不超过该值的最大元素**,再计算二者之差。核心方案是利用 `join_asof` 的 `backward` 策略,全程基于表达式链式操作,无需 python 循环或 `apply`。

在 Polars 中处理此类“查找最近下界(floor lookup)+ 差值”任务时,最高效、最符合声明式风格的方式是使用 join_asof —— 它专为有序键的近似连接设计,性能远超逐行 apply 或 map_dict。

✅ 解决方案:join_asof + backward 策略

假设原始 DataFrame 为 df,且 points = [0, 1500, 3000, 4500, 6000, 7500, 9000, 10500, 12000](已严格升序),执行以下链式操作:

points = [0, 1500, 3000, 4500, 6000, 7500, 9000, 10500, 12000]
df_points = pl.DataFrame({"point": points}).set_sorted("point")

result = (
    df.sort("bar")  # 关键:left_on 列需升序(join_asof 要求)
    .join_asof(df_points, left_on="bar", right_on="point")  # 默认 strategy="backward"
    .with_columns(baz=pl.col("bar") - pl.col("point"))
    .drop("point")
    .sort("foo")  # 恢复原始行序(可选)
)
? 原理说明: join_asof(..., strategy="backward") 对左表每行 bar=y,在右表 point 中查找满足 point ≤ y 的最大 point 值(即 floor)。 因 df_points 已通过 .set_sorted("point") 标记为有序,Polars 可跳过排序开销,直接二分查找,时间复杂度为 O(n log m)。 最终 baz = bar - point 即为所求差值。

⚠️ 注意事项

  • 必须保证 points 已升序,并调用 .set_sorted("point") 显式声明;否则 join_asof 行为未定义或报错。
  • join_asof 要求左表 left_on 列(此处为 "bar")在连接前已排序(.sort("bar") 不可省略),否则结果不正确。
  • 若 bar 中存在小于 points[0](即 0)的值,point 将为 null,导致 baz 也为 null。如需兜底(例如设为 bar 自身),可改用:
    .with_columns(baz=pl.col("bar") - pl.col("point").fill_null(0))

✅ 输出验证

结果与预期一致(部分截取):

┌─────┬───────┬──────┐
│ foo ┆ bar   ┆ baz  │
│ --- ┆ ---   ┆ ---  │
│ i64 ┆ i64   ┆ i64  │
╞═════╪═══════╪══════╡
│ 86  ┆ 11592 ┆ 1092 │  ← 11592 - 10500 = 1092
│ 109 ┆ 2765  ┆ 1265 │  ← 2765 - 1500 = 1265
│ 160 ┆ 1134  ┆ 1134 │  ← 1134 - 0 = 1134
└─────┴───────┴──────┘

此方法兼具高性能、可读性与可扩展性,是 Polars 生态中处理分段基准映射类问题的标准范式。


# python  # app 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】  ChatGPT 4.0官网入口地址 ChatGPT在线体验官网  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  昵图网官网入口 昵图网素材平台官方入口  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  如何在阿里云ECS服务器部署织梦CMS网站?  高性价比服务器租赁——企业级配置与24小时运维服务  Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  微信小程序 闭包写法详细介绍  JS碰撞运动实现方法详解  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  Laravel如何实现API版本控制_Laravel版本化API设计方案  大同网页,大同瑞慈医院官网?  网站制作企业,网站的banner和导航栏是指什么?  Laravel如何使用模型观察者?(Observer代码示例)  网站建设要注意的标准 促进网站用户好感度!  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  如何在宝塔面板中修改默认建站目录?  Laravel如何创建自定义中间件?(Middleware代码示例)  javascript如何操作浏览器历史记录_怎样实现无刷新导航  Laravel如何保护应用免受CSRF攻击?(原理和示例)  如何正确选择百度移动适配建站域名?  Laravel如何记录自定义日志?(Log频道配置)  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  手机网站制作与建设方案,手机网站如何建设?  Laravel如何发送邮件和通知_Laravel邮件与通知系统发送步骤  Laravel如何配置任务调度?(Cron Job示例)  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  C++时间戳转换成日期时间的步骤和示例代码  Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】  Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】  三星网站视频制作教程下载,三星w23网页如何全屏?  ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】  制作电商网页,电商供应链怎么做?  详解Android——蓝牙技术 带你实现终端间数据传输  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  如何在云服务器上快速搭建个人网站?  如何在搬瓦工VPS快速搭建网站?  Laravel如何为API编写文档_Laravel API文档生成与维护方法  Laravel如何使用Vite进行前端资源打包?(配置示例)  图册素材网站设计制作软件,图册的导出方式有几种?  Laravel怎么判断请求类型_Laravel Request isMethod用法  香港服务器如何优化才能显著提升网站加载速度?  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤