为什么 lubridate 的 parse_date_time 与 lapply 一起工作,但与 sapply 一起失败?

Why does lubridate's parse_date_time work with lapply, but fail with sapply?

给定:以下 4x2 数据帧

df <- as.data.frame(
  stringsAsFactors = FALSE,
  matrix(
    c("2014-01-13 12:08:02", "2014-01-13 12:19:46",
      "2014-01-14 09:59:09", "2014-01-14 10:05:09",
      "6-18-2016 17:43:42",  "6-18-2016 18:06:59",
      "6-27-2016 12:16:47",  "6-27-2016 12:29:05"),
    nrow = 4, ncol = 2, byrow = TRUE
  )
)
colnames(df) <- c("starttime", "stoptime")

目标:相同的数据帧,但所有值都替换为以下 lubridate 函数调用的 return 值:

f <- function(column) {
  parse_date_time(column, orders = c ("ymd_hms", "mdy_hms"), tz = "ETZ")
}

这是 sapply 调用,其结果包含奇怪的整数:

df2 <- sapply(df, FUN = f) # has values like `1467030545`

这里是 lapply 调用,按预期工作:

df2 <- lapply(df, FUN = f) # has values like `2016-06-27 12:29:05`

我理解 sapply return 是最简单的数据结构,而 lapply return 是列表。我准备用 df2 <- data.frame(df2) 跟进 sapply 调用,以根据需要得到一个数据框。我的问题是:

为什么 parse_date_time 函数在 lapply 中的行为与预期一致,但在 sapply?

原因是sapply默认有simplify = TRUE,当list元素的长度或尺寸相同时,它简化为vectormatrix。在内部,日期时间 类 存储为数字,

typeof(parse_date_time(df$starttime, orders = c("ymd_hms", "mdy_hms"), tz = "ETZ"))
#[1] "double"

class 是 'POSIXct`

class(parse_date_time(df$starttime, orders = c("ymd_hms", "mdy_hms"), tz = "ETZ"))
#[1] "POSIXct" "POSIXt"  

所以它在进行 matrix 转换时强制执行此操作,而在 list 中它保留 class 格式。

如果我们对 data.frame 感兴趣,那么我们创建 'df' 的副本并使用 [] 获得与 'df'[=24= 相同的结构]

df2 <- df
df2[] <-  lapply(df, FUN = function(column) {
     parse_date_time(column, orders = c("ymd_hms", "mdy_hms"), tz = "ETZ")
   })

df2
#           starttime            stoptime
#1 2014-01-13 12:08:02 2014-01-13 12:19:46
#2 2014-01-14 09:59:09 2014-01-14 10:05:09
#3 2016-06-18 17:43:42 2016-06-18 18:06:59
#4 2016-06-27 12:16:47 2016-06-27 12:29:05