R语言中用replicate构建tibble时,Date类型为何被转为数值?
解决replicate()将日期转换为整数的问题
我明白你遇到的困扰了——用replicate()生成日期时,结果被转成了Unix时间戳格式的整数,而非预期的日期类型。咱们先拆解问题根源,再给出几个实用的解决办法。
问题本质
replicate()其实是包装了simplify = "array"参数的sapply(),这类函数的核心特性是自动简化输出结果。而lubridate生成的日期对象(比如POSIXct)本质是带时间属性的数值向量,当sapply()/replicate()做简化时,会直接丢弃这些属性,只留下底层的数值(也就是从1970年1月1日到目标日期的秒数),这就是你看到整数的原因。哪怕你自定义了replicate2用sapply实现,也绕不开这个简化逻辑。
最优解决方案:用purrr的map系列函数替代replicate
purrr包的map()系列函数不会自动简化结果,能完整保留日期对象的类型和属性。这里有两种简洁的写法:
方法1:用map_vec()直接生成日期向量
library(tidyverse); library(reticulate) faker <- import("faker") fake <- faker$Faker() make_df <- function(N){ txns <- tibble( date_time = map_vec(1:N, ~ fake$date_time_between(start_date = "-1y", end_date = "now") %>% str_extract("[0-9-]*") %>% lubridate::parse_date_time("Ymd")) ) return(txns) } make_df(5)
运行后会得到预期的日期格式:
#> # A tibble: 5 x 1 #> date_time #> <dttm> #> 1 2018-11-06 00:00:00 #> 2 2018-12-15 00:00:00 #> 3 2018-09-25 00:00:00 #> 4 2019-01-15 00:00:00 #> 5 2018-07-08 00:00:00
方法2:用map()生成列表后展平
如果更习惯map()的写法,可以先生成列表,再用flatten_dttm()转成日期向量:
make_df <- function(N){ txns <- tibble( date_time = map(1:N, ~ fake$date_time_between(start_date = "-1y", end_date = "now") %>% str_extract("[0-9-]*") %>% lubridate::parse_date_time("Ymd")) %>% flatten_dttm() ) return(txns) }
备选方案:手动转换回日期格式
如果你不想更换函数,也可以在replicate()之后,用lubridate::as_datetime()把整数重新转成日期:
make_df <- function(N){ txns <- tibble( date_time = replicate(N, fake$date_time_between(start_date = "-1y", end_date = "now") %>% str_extract("[0-9-]*") %>% lubridate::parse_date_time("Ymd")) %>% as_datetime() ) return(txns) }
不过这种方法属于“先破坏再修复”,不如直接用map系列函数来得优雅。
内容的提问来源于stack exchange,提问作者RobertMyles
相关产品推荐
相关产品推荐

