使用case_when处理日期时遇向量长度不匹配警告的解决问询
解决日期分组时的向量长度不匹配警告问题
问题场景
你有如下数据集和日期向量:
my_data <- data.frame(date = as.Date(c("2022-03-08","2023-03-07","2022-11-29","2024-02-22")), value = 1:4) tox_date_1q <- as.Date(c("2022-03-08","2023-03-07","2024-02-21")) tox_date_3q <- as.Date(c("2022-06-21","2022-09-14","2022-11-29","2023-06-05","2023-09-13","2023-11-14"))
想要给my_data添加group列,将每行分为指定类别,但运行以下代码时出现向量长度不匹配的警告:
my_data <- my_data |> mutate(group = case_when( date %in% tox_date_1q ~ "tox_date_1q", date %in% tox_date_3q ~ "tox_date_3q", date > as.Date(tox_date_1q-30) & date < as.Date(tox_date_1q+30) ~ "tox_period_1q", date > as.Date(tox_date_3q-30) & date < as.Date(tox_date_3q+30) ~ "tox_period_3q", .default = "other" ))
警告信息:
Warning message: There were 4 warnings in `mutate()`. The first warning was: ℹ In argument: `group = case_when(...)`. Caused by warning in `>.default`: ! longer object length is not a multiple of shorter object length
问题原因
问题出在判断日期是否在前后30天区间的代码段:
date > as.Date(tox_date_1q-30) & date < as.Date(tox_date_1q+30) ~ "tox_period_1q", date > as.Date(tox_date_3q-30) & date < as.Date(tox_date_3q+30) ~ "tox_period_3q",
这里date是长度为4的向量(对应my_data的4行),而tox_date_1q是长度为3的向量,tox_date_3q是长度为6的向量。R会尝试循环较短的向量来匹配较长的向量长度,这不仅触发警告,还会导致逻辑错误——你需要判断的是单个日期是否落在任意一个tox_date的前后30天范围内,而非循环比较向量元素。
解决方案
方法1:使用rowwise()逐行处理
通过rowwise()让每行单独计算,结合any()判断当前日期是否满足任意一个区间条件:
library(dplyr) my_data <- my_data |> rowwise() |> mutate( group = case_when( date %in% tox_date_1q ~ "tox_date_1q", date %in% tox_date_3q ~ "tox_date_3q", any(date > tox_date_1q - 30 & date < tox_date_1q + 30) ~ "tox_period_1q", any(date > tox_date_3q - 30 & date < tox_date_3q + 30) ~ "tox_period_3q", .default = "others" ) ) |> ungroup()
方法2:使用purrr::map_lgl()批量判断
借助purrr包的map_lgl()遍历每个日期,生成逻辑向量后再分组:
library(dplyr) library(purrr) my_data <- my_data |> mutate( # 先判断每个日期是否在1q的任意区间内 in_1q_period = map_lgl(date, ~any(.x > tox_date_1q - 30 & .x < tox_date_1q + 30)), # 判断每个日期是否在3q的任意区间内 in_3q_period = map_lgl(date, ~any(.x > tox_date_3q - 30 & .x < tox_date_3q + 30)), # 生成group列 group = case_when( date %in% tox_date_1q ~ "tox_date_1q", date %in% tox_date_3q ~ "tox_date_3q", in_1q_period ~ "tox_period_1q", in_3q_period ~ "tox_period_3q", .default = "others" ) ) |> # 移除临时逻辑列 select(-in_1q_period, -in_3q_period)
两种方法都能解决向量长度不匹配的问题,且逻辑符合需求:优先匹配精确日期,再判断是否在任意目标日期的前后30天区间,最后归为其他类别。
内容的提问来源于stack exchange,提问作者pinawa
相关产品推荐
相关产品推荐

