基于Python Polars实现多条件DataFrame的类Vlookup操作
批量匹配Excel表格并添加SortInfo字段
问题背景
需要将"分拣信息表"中的SortInfo字段匹配到待匹配表格的对应行,匹配规则基于街道、邮编、城市的完全匹配,同时门牌号需符合分拣信息表中指定的范围与奇偶条件。
分拣信息表结构
| street | Hnr_from | Hnr_to | hnr_cond | Postcode | City | SortInfo |
|---|---|---|---|---|---|---|
| Hasel | 6 | 8 | 0 | 49082 | Osnb | OS1-01 |
| Hasel | 1 | 5 | 1 | 49083 | Osnb | OS1-02 |
| Mosel | 4 | 6 | 2 | 49084 | Munst | MU1-01 |
hnr_cond说明:0=门牌号全部匹配,1=仅奇数匹配,2=仅偶数匹配
待匹配表格结构
| street | Hnr | Postcode | City |
|---|---|---|---|
| Hasel | 7 | 49082 | Osnb |
| Mosel | 4 | 49084 | Munst |
此前尝试的单行处理代码
原代码仅能处理单条数据,无法批量处理待匹配表格的所有行:
import polars as pl xlsx_file = "Path/to/Sortinfo-file.xlsx" df = pl.read_excel(xlsx_file) searched_nr = 3 searched_str = "Mosel" searched_postc = 49088 searched_city = "Osnbr" filtered_df = df.filter( (searched_nr >= df['Hnr_from']) & (searched_nr <= df['Hnr_to']) & (((searched_nr % 2 == 0) & (df['hnr_cond'] == '2')) | ((searched_nr % 2 == 1) & (df['hnr_cond'] == '1')) | (df['hnr_cond'] == '0')) & (searched_str == df['street']) & (searched_postc == df['Postcode']) & (searched_city == df['City']) ) SortInfo = None if not filtered_df.is_empty(): # 原代码存在笔误,应取SortInfo而非bezirk SortInfo = filtered_df.to_pandas()['SortInfo'].iloc[0] print(SortInfo)
待匹配表格加载代码
xlsx_file = "path/to/other-file.xlsx" df_searched = pl.read_excel(xlsx_file) searched_number = df_seached['Hnr'] searched_street = df_seached['street'] searched_postcode = df_seached['Postcode'] searched_City = df_searched['City']
期望结果
最终需得到包含SortInfo字段的匹配后表格:
| street | Hnr | Postcode | City | SortInfo |
|---|---|---|---|---|
| Hasel | 7 | 49082 | Osnb | OS1-01 |
| Mosel | 4 | 49084 | Munst | MU1-01 |
解决方案
使用Polars的条件连接实现批量匹配,效率更高且逻辑清晰:
import polars as pl # 加载两个表格 df_sortinfo = pl.read_excel("Path/to/Sortinfo-file.xlsx") df_searched = pl.read_excel("path/to/other-file.xlsx") # 执行条件连接 result_df = df_searched.join( df_sortinfo, # 先匹配基础字段:街道、邮编、城市 on=["street", "Postcode", "City"], # 添加门牌号范围与奇偶判断条件 condition=( (pl.col("Hnr") >= pl.col("Hnr_from")) & (pl.col("Hnr") <= pl.col("Hnr_to")) & pl.when(pl.col("hnr_cond") == 0) .then(True) .when(pl.col("hnr_cond") == 1) .then(pl.col("Hnr") % 2 == 1) .when(pl.col("hnr_cond") == 2) .then(pl.col("Hnr") % 2 == 0) .otherwise(False) ), # 保留待匹配表所有行,未匹配到的SortInfo为null how="left" ).select( # 按期望结果排序字段 "street", "Hnr", "Postcode", "City", "SortInfo" ) # 输出结果 print(result_df)
代码说明
- 条件连接:通过
join的condition参数同时校验基础匹配字段和门牌号规则,避免交叉连接的性能浪费。 - 奇偶判断优化:用
pl.when语法清晰处理hnr_cond的三种场景,比多或条件更易维护。 - 左连接逻辑:
how="left"确保待匹配表的所有行都被保留,无匹配时SortInfo字段为null。 - 字段整理:最后通过
select调整字段顺序,与期望结果完全对齐。
注:若分拣信息表中存在多条匹配同一行的记录,需根据实际需求添加
unique()或调整连接逻辑,确保每行仅保留一个SortInfo。
内容的提问来源于stack exchange,提问作者Yannik Brüggemann
相关产品推荐
相关产品推荐

