为何R中sapply处理Date类型返回数值而非日期?
为什么R中
sapply返回数值而非Date类型? 问题原因
在R里,Date类型本质是带有Date类属性的整数(存储的是从1970-01-01开始的累计天数)。而sapply的默认行为是自动简化输出结果:当它完成对每个元素的调用后,会尝试将结果合并为更紧凑的结构,这个过程中会触发unlist操作,而unlist会丢弃对象的类属性,只保留底层的数值,最终就得到了纯数值向量,而非预期的Date类型。
比如运行这段代码时:
set.seed(0); sapply(1:4, function(x) lubridate::ymd("2023-01-01")) %>% str()
返回的19358就是2023-01-01对应的天数(从1970-01-01到该日期的天数)。
解决方案
方法1:用lapply返回列表再合并
lapply不会自动简化结果,会保留每个元素的Date类属性,之后用do.call(c, ...)合并成Date向量:
# 定义随机日期生成函数 generateRandomDate <- function(start_date, end_date) { random_days <- sample(0:(end_date - start_date), 1) start_date + lubridate::days(random_days) } # 生成结果 set.seed(0) date_list <- lapply(1:12, function(x) generateRandomDate(lubridate::ymd("2023-01-01"), lubridate::ymd("2023-01-31"))) date_vec <- do.call(c, date_list) str(date_vec) # Date[1:12], format: "2023-01-13" "2023-01-02" "2023-01-27" ...
方法2:强制sapply返回列表再合并
给sapply设置simplify = FALSE,让它返回列表而非自动简化,再合并:
set.seed(0) date_list <- sapply(1:12, function(x) generateRandomDate(lubridate::ymd("2023-01-01"), lubridate::ymd("2023-01-31")), simplify = FALSE) date_vec <- do.call(c, date_list)
方法3:用vapply指定输出类型
vapply可以提前指定输出的类型,直接生成Date向量,避免后续转换:
set.seed(0) date_vec <- vapply(1:12, function(x) generateRandomDate(lubridate::ymd("2023-01-01"), lubridate::ymd("2023-01-31")), FUN.VALUE = lubridate::ymd("1970-01-01")) str(date_vec)
方法4:使用purrr包的map_vec(tidyverse生态)
如果你习惯使用tidyverse工具,purrr::map_vec可以自动保留元素类型,直接输出Date向量:
library(purrr) set.seed(0) date_vec <- map_vec(1:12, ~generateRandomDate(lubridate::ymd("2023-01-01"), lubridate::ymd("2023-01-31"))) str(date_vec)
内容的提问来源于stack exchange,提问作者IVIM
相关产品推荐
相关产品推荐

