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

dplyr::case_when动态引用列值进行日期比较的异常问题

解决dplyr case_when动态日期列比较结果异常的问题

你遇到的问题核心是动态列名引用时没有逐行处理,直接用!!!sym或get会获取整个列的向量进行比较,而非当前行的单个日期值,导致逻辑判断完全混乱。

解决方案1:用rowwise()+get逐行处理

这是最贴合dplyr风格的写法,通过rowwise()让代码逐行执行,确保get()能拿到当前行对应列的单元格值:

library(dplyr)

df_fixed <- df %>%
  rowwise() %>%
  mutate(
    # 动态拼接目标日期列名
    vac_col = paste0("date_", hlp_vac),
    inf_col = paste0("date_infection_", to_modif),
    # 修正earlier和later列
    earlier = case_when(
      get(vac_col) < get(inf_col) ~ "Vacation",
      get(vac_col) > get(inf_col) ~ "Infection",
      TRUE ~ earlier  # 日期为空或相等时保留原值
    ),
    later = case_when(
      get(vac_col) < get(inf_col) ~ "Infection",
      get(vac_col) > get(inf_col) ~ "Vacation",
      TRUE ~ later
    )
  ) %>%
  ungroup()

# 验证id=215的结果
df_fixed %>% filter(id == "215")

执行后id=215的earlier会正确显示为Vacation,later为Infection,符合日期比较逻辑。

解决方案2:用purrr::pmap逐行映射

如果需要更灵活的行内逻辑,可使用pmap逐行处理每一行数据:

library(purrr)
library(dplyr)

df_fixed <- df %>%
  bind_cols(
    pmap_dfr(., function(...) {
      row <- tibble(...)
      vac_date <- pull(row, paste0("date_", row$hlp_vac))
      inf_date <- pull(row, paste0("date_infection_", row$to_modif))
      
      # 仅当两个日期都非空时修正,否则保留原值
      if (!is.na(vac_date) && !is.na(inf_date)) {
        list(
          earlier = if(vac_date < inf_date) "Vacation" else "Infection",
          later = if(vac_date < inf_date) "Infection" else "Vacation"
        )
      } else {
        list(earlier = row$earlier, later = row$later)
      }
    })
  )

关键原因说明

之前的错误在于:!!!sym或get在非rowwise环境中会直接操作整个列向量,比如get("date_Vacation4")会拿到所有行的Vacation4日期,和get("date_infection_m30")的整个列比较,得到的是一个布尔向量,case_when会按向量的位置匹配,而非逐行判断,最终导致结果完全不符合预期。而rowwise()会强制函数逐行执行,让get()每次只取当前行的对应值,比较逻辑才会正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:25:36