首页 > 解决方案 > 从 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`

现在将日期列转换为字符:

  1. 使用 $

> 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"

  1. 利用 [[ ]]

> 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"

  1. 利用 [ , ]

> as.character(dat[ , 2]) [1] "c(948585600, 948672000, 948758400, 948844800, 948931200, 949017600, 949104000, 949190400, 949276800)"

为什么第三种情况会产生不同的结果?我相信前两种情况返回向量,第三种情况返回数据帧,但为什么会有所不同?案例3中的数字来自哪里?(这些数字与 Excel 用来表示日期的数字不对应。)

标签: r

解决方案


不同之处在于你有一个tibble,而不是一个data.frame。如果data.frame子集将返回单列或单行,则默认情况下将简化为向量;您可以选择使用drop=F(见下文)来防止这种情况。

这在基于 - 的包中被认为是一个“好特性” tidyverse:做一件事,总是返回相同的类/结构等。以编程方式可能无法预测的方式返回 alist或 a的函数可以被认为是一个问题。vector(因此,当我以编程方式处理原始data.frame恶习时tbls,我经常,drop=FALSE在需要防范它时添加。)

类似地,你有没有被sapplyor咬过mapply?如果返回的值都是相同的长度/类,那么你会得到 avector或 a matrix,但如果任何长度或类不一样,那么你会得到 a list,无论你是否期待它。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。(这同样适用于POSIXtDate类。)

(至于他们被强制要求的实际数字,我不知道临时......)


推荐阅读