使用lubridate转换不完整日期字符串出现解析警告的原因排查
警告原因
警告源于case_when的执行特性:它会先全局计算所有分支的表达式,再根据条件筛选对应结果,而非仅执行符合条件的分支。
放到你的代码里看:
- 第一个分支的
ymd(paste(a, "-01", sep = ""))会对整个a向量运算,把"2021"转成"2021-01",但ymd要求完整的年-月-日格式,解析这个不完整字符串时失败,触发警告。 - 第二个分支的
ymd(paste(a, "-01-01", sep=""))同样会遍历整个a向量,把"2021-01"转成"2021-01-01-01",这是无效日期格式,解析失败再次抛出警告。
虽然最终结果正确,但过程中无效的解析尝试导致了警告。
解决方法
方法1:逐行计算(用rowwise())
让case_when逐行处理每个元素,避免全局计算带来的无效解析:
library(dplyr) library(lubridate) aa = data.frame(a = c("2021-01", "2021")) bb = aa %>% rowwise() %>% mutate(aa = case_when( nchar(a) == 7 ~ ymd(paste0(a, "-01")), nchar(a) == 4 ~ ymd(paste0(a, "-01-01")) )) %>% ungroup()
方法2:用ymd自带的truncated参数(最简洁)
lubridate::ymd的truncated参数可以自动补全缺失的日期部分,完全不需要case_when:
library(dplyr) library(lubridate) aa = data.frame(a = c("2021-01", "2021")) bb = aa %>% mutate(aa = ymd(a, truncated = 2))
truncated=2表示允许最多缺失2个日期分量:仅给年份时自动补-01-01,给年月时自动补-01,完全匹配你的需求,且无警告。
方法3:用if_else替代case_when
if_else是向量化条件判断,会分别对符合/不符合条件的元素执行对应表达式:
library(dplyr) library(lubridate) aa = data.frame(a = c("2021-01", "2021")) bb = aa %>% mutate(aa = if_else( nchar(a) == 7, ymd(paste0(a, "-01")), ymd(paste0(a, "-01-01")) ))
内容的提问来源于stack exchange,提问作者rashette
相关产品推荐
相关产品推荐

