如何用dplyr::case_when()匹配两个dataframe的值
用dplyr::case_when()实现跨DataFrame值匹配
给定数据
df_1 = data.frame( year = rep(c(2001:2020), 5), area = c(rep("8", 20), rep("9", 20), rep("10", 20), rep("11", 20), rep("12", 20)) ) df_2 = data.frame( val = rnorm(20, mean = 10, sd = 0.5), year = rep(c(2001:2020)) )
需求
为df_1新增列new,满足:
- 所有区域且
year < 2002时,值为0; - 非"12"区域的所有年份,值为0;
- "12"区域且
year >= 2002时,取df_2对应年份的val值。
原有for循环实现
df_1_some_matched = df_1 %>% dplyr::mutate( new = ifelse( area == "12" & year < 2002, 0, ifelse( area != 12, 0, NA ) ) ) for(yr in 2002:2020) { df_1[which(df_1$area == "12" & df_1$year == yr), "new"] = df_2[which(df_2$year == yr), "val"] }
完整的case_when()实现
推荐先通过left_join关联数据,再用case_when按条件赋值,这种方式更高效且易读:
df_1_case_matched = df_1 %>% dplyr::left_join(df_2, by = "year") %>% dplyr::mutate( new = dplyr::case_when( year < 2002 ~ 0, area != "12" ~ 0, # 剩余满足area="12"且year>=2002的行,直接取val TRUE ~ val ) ) %>% # 可选:移除临时关联的val列 dplyr::select(-val)
如果不想提前关联数据,也可以直接在case_when中用match匹配年份:
df_1_case_matched = df_1 %>% dplyr::mutate( new = dplyr::case_when( year < 2002 ~ 0, area != "12" ~ 0, area == "12" & year >= 2002 ~ df_2$val[match(year, df_2$year)] ) )
关键说明
case_when按顺序判断条件,优先级从高到低:
- 先处理所有年份小于2002的情况;
- 再处理非12区域的所有情况;
- 最后剩下的自然是"12"区域且年份>=2002的行,直接取对应值即可。
内容的提问来源于stack exchange,提问作者colebrookson
相关产品推荐
相关产品推荐

