如何在Python的两个DataFrame中实现精确匹配或下一个较大项的查找?
实现Excel式精确/下一个较大项匹配
问题背景
需要为Wins DataFrame匹配Levels中的Level字段,匹配规则:
- 若
Wins Needed与Levels["Wins"]精确匹配,直接对应; - 若无精确匹配,匹配**第一个大于
Wins Needed的Levels["Wins"]**对应的Level。
已知两个DataFrame结构:
Wins DataFrame
import numpy as np import pandas as pd np.random.seed(1) Wins_Range = np.arange(1,101,1) Wins = pd.DataFrame({"Wins Needed": Wins_Range})
结构示例:
| Wins Needed | |
|---|---|
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| ... | ... |
| 99 | 100 |
Levels DataFrame
Levels_Range = np.arange(1,101,1) Levels = pd.DataFrame({"Level": Levels_Range}) Levels["Wins"]=np.random.choice([1,2,3,4,5],size=len(Levels), p=[0.2,0.2,0.2,0.2,0.2]).cumsum()
结构示例:
| Level | Wins | |
|---|---|---|
| 0 | 1 | 3 |
| 1 | 2 | 7 |
| 2 | 3 | 8 |
| ... | ... | ... |
| 99 | 100 | 294 |
注意:Levels["Wins"]为float类型,Wins["Wins Needed"]为int类型,直接使用merge无法实现需求。
解决方案:使用pd.merge_asof
merge_asof专门用于按键进行最近邻匹配,支持指定匹配方向,完美契合本次需求。
步骤1:统一数据类型
先将两个匹配键的类型统一,避免类型不匹配导致的问题:
# 将Wins的Wins Needed转为float,与Levels的Wins类型一致 Wins["Wins Needed"] = Wins["Wins Needed"].astype(float)
步骤2:确保键排序(关键)
merge_asof要求左表和右表的匹配键必须是升序排列的。本次数据本身已满足,但显式排序可避免意外:
Wins = Wins.sort_values("Wins Needed") Levels = Levels.sort_values("Wins")
步骤3:执行匹配
设置direction='forward',表示匹配第一个大于等于左表键的值,正好对应"精确匹配或下一个较大项"的规则:
result = pd.merge_asof( Wins, Levels, left_on="Wins Needed", right_on="Wins", direction="forward", how="left" )
结果示例
匹配后result的部分数据:
| Wins Needed | Level | Wins | |
|---|---|---|---|
| 0 | 1.0 | 1 | 3.0 |
| 1 | 2.0 | 1 | 3.0 |
| 2 | 3.0 | 1 | 3.0 |
| 3 | 4.0 | 2 | 7.0 |
| 4 | 5.0 | 2 | 7.0 |
可以看到:
Wins Needed=3精确匹配Levels["Wins"]=3,对应Level1;Wins Needed=4无精确匹配,匹配到第一个更大的Wins=7,对应Level2。
内容的提问来源于stack exchange,提问作者Naor
相关产品推荐
相关产品推荐

