You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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按顺序判断条件,优先级从高到低:

  1. 先处理所有年份小于2002的情况;
  2. 再处理非12区域的所有情况;
  3. 最后剩下的自然是"12"区域且年份>=2002的行,直接取对应值即可。

内容的提问来源于stack exchange,提问作者colebrookson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 10:45:48