as.Date返回不同​​的格式,如果是否是sapply

时间:2015-06-17 07:26:55

标签: r date datetime format as.date

我有一个数据框,其中包含一个日期列,我需要将其转换为格式R,并将其识别为日期。

> dataframe
        Date        Sum
1   06/09/15       2.51
2   06/09/15       3.75
3   06/09/15       3.50
...

我首先使用sapply转换它:

> dataframe$Date2<-sapply(dataframe$Date,as.Date,format="%m/%d/%y")

这将日期作为1970年1月1日的天数返回:

> dataframe
        Date        Sum      Date2
1   06/09/15       2.51      16595
2   06/09/15       3.75      16595
3   06/09/15       3.50      16595
...

后来我尝试在没有sapply的情况下进行转换:

> dataframe$Date3<-as.Date(dataframe$Date,format="%m/%m/%d")

这反过来又回来了

> dataframe
        Date        Sum      Date2       Date3
1   06/09/15       2.51      16595  2015-09-15
2   06/09/15       3.75      16595  2015-09-15
3   06/09/15       3.50      16595  2015-09-15
...

这是两种非常不同的,显然不兼容的格式。为什么sapply会返回一种格式(从原点开始的几天),而不使用它会返回另一种格式(%Y-%m-%d)?

现在,显然我可以忽略一种方法并且永远不会将sapplyas.Date一起使用,但我想知道为什么它的读取方式不同。我也在努力将Date3向量转换为Date2格式。

因此,我有两个问题:

  1. 为什么sapply提供不同的日期格式?
  2. 如何将日期可识别的序列(例如mm / dd / yyyy)转换为1970年1月1日以来的天数?

3 个答案:

答案 0 :(得分:2)

以下是原始问题第二部分的答案。要获得格式mm/dd/yyyy格式的日期(1970年1月1日)以来的天数,您可以使用as.Date()函数:

some.date <- as.Date("06/17/2015", "%m/%d/%Y")
days.since.epoch <- unclass(some.date)

> days.since.epoch
[1] 16616

在内部,R根据自纪元(1970年1月1日)以来的天数存储日期对象some.date,并且调用unclass()显示此内部表示。

答案 1 :(得分:1)

使用日期时,我喜欢使用lubridate,因为它在我眼中更容易使用,而且比基本功能更直观。
您可以使用以下代码完成第二个问题:

require(lubridate)
dataframe$Date2<-difftime(dataframe$Date3,dmy("01-01-1970"),units="days")

取决于您是否希望将1970年1月1日作为第1天,您可能需要在此行的末尾添加+1。

我没有直接使用sapply和tapply(我更喜欢使用plyr)所以我无法帮助解决你的第一个问题。

答案 2 :(得分:1)

1。

如果不使用参数simplify=FALSE,则sapply将使用命令unlist将答案从列表转换为向量。 unlist将列表元素强制为普通类型。来自manual

  

在取消列出过程中,可能的情况下,列表元素被强制转换为公共模式,因此结果通常以字符向量结尾。向量将被强制为层次结构中组件的最高类型NULL <原始<逻辑<整数

由于Date不是层次结构的一部分,因此unlist无法强制使用Date。我不确定为什么unlist选择强制转换为整数(而不是字符),但这可能与Date对象存储为整数的事实有关。

2。

要将Date转换为自1970年1月1日以来的天数,可以使用as.numeric

today=Sys.Date()
> today
[1] "2019-04-16"
> as.numeric(today)
[1] 18002

然后返回

> as.Date(18002, origin="1970-01-01")
[1] "2019-04-16"