提问人:fsure 提问时间:11/15/2023 最后编辑:Julianfsure 更新时间:11/15/2023 访问量:47
在 df1 和 df2 之间执行left_join,其中 df2 给出了 df1 中连接变量的范围
Perform left_join between df1 and df2 where df2 gives a range for the joining variable in df1
问:
我正在尝试合并两个数据帧。
df1
包含包含列和 的公司级别数据。Say 看起来像这样:company_name
industry_code
df1
company_name | industry_code |
---|---|
一个 | 33 |
B | 43 |
C | 56 |
D | 88 |
df2
包含。Say 看起来像这样:industry_name
min_code
max_code
df2
industry_name | min_code | max_code |
---|---|---|
烟 | 10 | 19 |
食物 | 20 | 39 |
关心 | 40 | 69 |
制造业 | 70 | 99 |
我想将行业数据合并到公司数据中。这样,在合并后,数据如下所示:df2
df1
company_name | industry_code | industry_name |
---|---|---|
一个 | 33 | 食物 |
B | 43 | 关心 |
C | 56 | 关心 |
D | 88 | 制造业 |
请看下面我失败的尝试:
# first attempt
df1 %>%
left_join(df2, by = c("industry_code" = "min_code"))
# second attempt
df1 %>%
mutate(industry_name = ifelse(between(industry_code, df2$min_code, df2$max_code), df2$industry_name, NA)
答:
4赞
Mark
11/15/2023
#1
正如 Jon 已经说过的,使用 dplyr 最简单的答案是使用:join_by()
df1 |>
left_join(df2, join_by(between(industry_code, min_code, max_code))) |>
select(-min_code, -max_code)
输出:
# A tibble: 4 × 3
company_name industry_code industry_name
<chr> <dbl> <chr>
1 A 33 Food
2 B 43 Care
3 C 56 Care
4 D 88 Manufacturing
第一次尝试的问题是,(我相信你已经知道了),行业代码与最小代码不匹配,所以你会得到 NA。
如果你稍微玩一下,第二次尝试的问题可以更清楚:
between(c(88, 88, 88, 88), df2$min_code, df2$max_code) # [1] FALSE FALSE FALSE TRUE
between(c(33, 33, 33, 33), df2$min_code, df2$max_code) # [1] FALSE TRUE FALSE FALSE
between(c(33, 33, 33, 33, 33), df2$min_code, df2$max_code)
# Error in between(c(33, 33, 33, 33, 33), df2$min_code, df2$max_code) :
# Incompatible vector lengths: length(x)==5 length(lower)==4 length(upper)==4. Each should be either length 1 or the length of the longest.
该代码不是根据每个最小值和最大值检查每个行业代码,而是根据第一个最小值和第一个最大值检查第一个行业代码,依此类推。
如果您仍然想使用这种方法,则使用 map_chr() 遍历industry_name是可行的。此外,您的样本数据中没有间隙,因此,如果您的真实数据也是如此,则可以使用基本 R,例如 .findInterval()
df2$industry_name[findInterval(df1$industry_code, df2$min_code)]
0赞
Yuriy Saraykin
11/15/2023
#2
数据表
library(data.table)
df2 <- data.frame(
stringsAsFactors = FALSE,
industry_name = c("Smoke", "Food", "Care", "Manufacturing"),
min_code = c(10L, 20L, 40L, 70L),
max_code = c(19L, 39L, 69L, 99L)
)
df1 <- data.frame(
stringsAsFactors = FALSE,
company_name = c("A", "B", "C", "D"),
industry_code = c(33L, 43L, 56L, 88L)
)
setDT(df1)
setDT(df2)
df2[df1, list(company_name, industry_code, industry_name), on = list(max_code >= industry_code, min_code <= industry_code)]
#> company_name industry_code industry_name
#> 1: A 33 Food
#> 2: B 43 Care
#> 3: C 56 Care
#> 4: D 88 Manufacturing
创建于 2023-11-15 with reprex v2.0.2
评论