tidyverse中用ifelse计算日期列最小值返回数值的解决方法
问题根因
这是R自带基础函数ifelse()的固有特性,和你使用的tidyverse 1.3.0版本没有关系。
R里的Date类型本质是存储数值的向量,数值记录的是距离1970年1月1日的天数,只是额外带了Date类标签,打印输出时才会显示成年月日格式。而基础ifelse()返回结果时会直接丢弃输入向量的原始类属性,日期的类标签丢失后,就会露出底层存储的数值18628——这个数正好就是2021-01-01对应的天数。
解决方法
你不需要每次都手动调用as.Date()指定origin参数做类型转换,有两个更稳妥的写法可以从根源避免类型丢失:
- 直接用dplyr提供的类型安全版本
if_else()替换基础ifelse(),这个函数做了严格的类型校验,会完整保留输入数据的原有类型,不会丢失Date属性,直接运行就能返回正确的日期结果:
library(tidyverse) df <- data.frame( the_date=c(as.Date("2021-01-01"), as.Date("2021-01-02")), keep=c(TRUE, TRUE)) # 直接返回Date类型的最小值2021-01-01 df %>% summarize(the_min=min(if_else(keep, the_date, NA)))
- 如果一定要使用基础
ifelse(),只要把替换值从默认的逻辑型NA改成Date类型的缺失值as.Date(NA),返回结果就会保留Date类,不需要事后再做格式转换:
df %>% summarize(the_min=min(ifelse(keep, the_date, as.Date(NA))))
你之前用的
as.Date(min(...), origin="1970-01-01")属于结果异常后的补救方案,能跑但容错率低,万一记错origin参数算出的日期会全部出错,不如前面两种写法靠谱。
内容的提问来源于stack exchange,提问作者dfrankow
相关产品推荐
相关产品推荐

