如何基于行业代码范围对df1与df2执行left_join合并?
按区间匹配合并数据框的解决方案
问题背景
我有两个数据框需要合并:
- df1是公司级数据,包含
company_name(公司名称)和industry_code(行业代码)列,示例数据:
| company_name | industry_code |
|---|---|
| A | 33 |
| B | 43 |
| C | 56 |
| D | 88 |
- df2是行业区间数据,包含
industry_name(行业名称)、min_code(最小代码)、max_code(最大代码)列,示例数据:
| industry_name | min_code | max_code |
|---|---|---|
| Smoke | 10 | 19 |
| Food | 20 | 39 |
| Care | 40 | 69 |
| Manufacturing | 70 | 99 |
目标是把df2的行业名称匹配到df1中,要求industry_code落在min_code和max_code的区间内,最终得到如下结果:
| company_name | industry_code | industry_name |
|---|---|---|
| A | 33 | Food |
| B | 43 | Care |
| C | 56 | Care |
| D | 88 | Manufacturing |
我试了两种方法都没成功:
# 第一次尝试 df1 %>% left_join(df2, by = c("industry_code" = "min_code")) # 第二次尝试 df1 %>% mutate(industry_name = ifelse(between(industry_code, df2$min_code, df2$max_code), df2$industry_name, NA))
失败原因
- 第一次用
left_join是精确匹配,只会把df1的industry_code和df2的min_code完全相等的行合并,根本没用到区间逻辑,自然不对。 - 第二次的
ifelse和between搞不定向量长度不匹配的问题:df1的每一行都要和df2的所有区间挨个比对,但直接传df2$min_code是把整个向量塞进去,逻辑判断全乱了,出不来正确结果。
正确实现方式
方法1:dplyr交叉连接+过滤
先把df1和df2的所有行交叉组合,再筛选出符合区间条件的行,最后保留需要的列:
library(dplyr) result <- df1 %>% cross_join(df2) %>% filter(industry_code >= min_code & industry_code <= max_code) %>% select(company_name, industry_code, industry_name)
方法2:fuzzyjoin模糊匹配
fuzzyjoin包专门处理非精确匹配,用fuzzy_left_join可以直接指定区间匹配规则,数据量大的时候比方法1效率高:
library(fuzzyjoin) library(dplyr) result <- df1 %>% fuzzy_left_join( df2, by = c("industry_code" = "min_code", "industry_code" = "max_code"), match_fun = list(`>=`, `<=`) ) %>% select(company_name, industry_code, industry_name)
两种方法都能得到你要的结果,根据数据量大小选就行。
内容的提问来源于stack exchange,提问作者fsure
相关产品推荐
相关产品推荐

