为什么 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
元素的长度或尺寸相同时,它简化为vector
或matrix
。在内部,日期时间 类 存储为数字,
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
给定:以下 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
元素的长度或尺寸相同时,它简化为vector
或matrix
。在内部,日期时间 类 存储为数字,
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