r - 从 Excel 导入 R 的日期在以不同方式转换为字符时会产生不同的结果
问题描述
将包含日期的 Excel 电子表格导入 R(使用 readxl)。例如
`# A tibble: 9 x 2
id date
<dbl> <dttm>
1 1 2000-01-23
2 2 2000-01-24
3 3 2000-01-25
4 4 2000-01-26
5 5 2000-01-27
6 6 2000-01-28
7 7 2000-01-29
8 8 2000-01-30
9 9 2000-01-31`
现在将日期列转换为字符:
- 使用 $
> as.character(dat$date)
[1] "2000-01-23" "2000-01-24" "2000-01-25" "2000-01-26" "2000-01-27" "2000-01-28" "2000-01-29" "2000-01-30" "2000-01-31"
- 利用 [[ ]]
> as.character(dat[[2]])
[1] "2000-01-23" "2000-01-24" "2000-01-25" "2000-01-26" "2000-01-27" "2000-01-28" "2000-01-29" "2000-01-30" "2000-01-31"
- 利用 [ , ]
> as.character(dat[ , 2])
[1] "c(948585600, 948672000, 948758400, 948844800, 948931200, 949017600, 949104000, 949190400, 949276800)"
为什么第三种情况会产生不同的结果?我相信前两种情况返回向量,第三种情况返回数据帧,但为什么会有所不同?案例3中的数字来自哪里?(这些数字与 Excel 用来表示日期的数字不对应。)
解决方案
不同之处在于你有一个tibble
,而不是一个data.frame
。如果data.frame
子集将返回单列或单行,则默认情况下将简化为向量;您可以选择使用drop=F
(见下文)来防止这种情况。
这在基于 - 的包中被认为是一个“好特性” tidyverse
:做一件事,总是返回相同的类/结构等。以编程方式可能无法预测的方式返回 alist
或 a的函数可以被认为是一个问题。vector
(因此,当我以编程方式处理原始data.frame
恶习时tbls
,我经常,drop=FALSE
在需要防范它时添加。)
类似地,你有没有被
sapply
or咬过mapply
?如果返回的值都是相同的长度/类,那么你会得到 avector
或 amatrix
,但如果任何长度或类不一样,那么你会得到 alist
,无论你是否期待它。sapply(..., simplify=FALSE)
这是“总是”使用orlapply(...)
或的理由之一mapply(..., SIMPLIFY=FALSE)
。purrr::map
这也是函数族的部分理由。
例子:
library(dplyr)
d1 <- data.frame(dt=seq.Date(as.Date('2000-01-23'),as.Date('2000-01-30'),by='day'))
d2 <- as.tbl(d1)
d1[,1]
# [1] "2000-01-23" "2000-01-24" "2000-01-25" "2000-01-26" "2000-01-27"
# [6] "2000-01-28" "2000-01-29" "2000-01-30"
d2[,1]
# # A tibble: 8 × 1
# dt
# <date>
# 1 2000-01-23
# 2 2000-01-24
# 3 2000-01-25
# 4 2000-01-26
# 5 2000-01-27
# 6 2000-01-28
# 7 2000-01-29
# 8 2000-01-30
为什么这会创造出一些时髦的东西?因为你在数据中有其他东西。
d1$id <- 1:nrow(d1)
d2$id <- 1:nrow(d2)
as.character(d2)
# [1] "c(10979, 10980, 10981, 10982, 10983, 10984, 10985, 10986)"
# [2] "1:8"
as.character(d1[,1])
# [1] "2000-01-23" "2000-01-24" "2000-01-25" "2000-01-26" "2000-01-27"
# [6] "2000-01-28" "2000-01-29" "2000-01-30"
as.character(d1[,1,drop=FALSE])
# [1] "c(10979, 10980, 10981, 10982, 10983, 10984, 10985, 10986)"
as.character(d2[,1])
# [1] "c(10979, 10980, 10981, 10982, 10983, 10984, 10985, 10986)"
当您在整个帧(无论是否)上调用函数时tibble
,它通常会将所有列转换为最低通用格式,character < numeric < integer
并且POSIXt
有效numeric
(使用 tz 信息),因此它被强制转换为numeric
. 因为里面没有非POSIXt
。(这同样适用于POSIXt
和Date
类。)
(至于他们被强制要求的实际数字,我不知道临时......)