Converting `dttm` to `date` formatting with as.Date and as_date give different results in R

*爱你&永不变心* 提交于 2021-02-18 12:51:14

问题


I have a large data set with individual columns for event times and dates. I ended up creating a master dttm object with both the times and dates together, but have had trouble when I try to filter based on the date. Here is a sample data set that reflects my own:

library(tidyverse)

d<- structure(list(date = structure(c(1530921600, 1531008000, 
1530403200, 1530489600, 1530576000, 1530489600, 1530576000, 1531008000, 
1530921600, 1530662400, 1530748800, 1531180800, 1530748800, 1531526400, 
1531526400, 1532044800, 1532131200, 1531180800, 1531353600, 1531353600
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), date_time = structure(c(1531019100, 
1531117500, 1530440640, 1530562440, 1530633240, 1530571920, 1530648900, 
1531037100, 1531010460, 1530717240, 1530808200, 1531237020, 1530813000, 
1531614060, 1531637640, 1532104320, 1532195220, 1531290120, 1531434300, 
1531409280), class = c("POSIXct", "POSIXt"), tzone = "")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -20L))

Here is the how the data look:

# A tibble: 20 x 2
   date                date_time  
   <dttm>              <dttm>             
 1 2018-07-07 00:00:00 2018-07-07 20:05:00
 2 2018-07-08 00:00:00 2018-07-08 23:25:00
 3 2018-07-01 00:00:00 2018-07-01 03:24:00
 4 2018-07-02 00:00:00 2018-07-02 13:14:00
 5 2018-07-03 00:00:00 2018-07-03 08:54:00
 6 2018-07-02 00:00:00 2018-07-02 15:52:00
 7 2018-07-03 00:00:00 2018-07-03 13:15:00
 8 2018-07-08 00:00:00 2018-07-08 01:05:00
 9 2018-07-07 00:00:00 2018-07-07 17:41:00
10 2018-07-04 00:00:00 2018-07-04 08:14:00
11 2018-07-05 00:00:00 2018-07-05 09:30:00
12 2018-07-10 00:00:00 2018-07-10 08:37:00
13 2018-07-05 00:00:00 2018-07-05 10:50:00
14 2018-07-14 00:00:00 2018-07-14 17:21:00
15 2018-07-14 00:00:00 2018-07-14 23:54:00
16 2018-07-20 00:00:00 2018-07-20 09:32:00
17 2018-07-21 00:00:00 2018-07-21 10:47:00
18 2018-07-10 00:00:00 2018-07-10 23:22:00
19 2018-07-12 00:00:00 2018-07-12 15:25:00
20 2018-07-12 00:00:00 2018-07-12 08:28:00

You can see that all of the dates match across columns; the only difference is the presence of time information. But, when I convert both columns to the date class using as.Date...

d$date<- as.Date(d$date)
d$date_time<- as.Date(d$date_time)

# A tibble: 20 x 2
   date       date_time 
   <date>     <date>    
 1 2018-07-07 2018-07-08
 2 2018-07-08 2018-07-09
 3 2018-07-01 2018-07-01
 4 2018-07-02 2018-07-02
 5 2018-07-03 2018-07-03
 6 2018-07-02 2018-07-02
 7 2018-07-03 2018-07-03
 8 2018-07-08 2018-07-08
 9 2018-07-07 2018-07-08
10 2018-07-04 2018-07-04
11 2018-07-05 2018-07-05
12 2018-07-10 2018-07-10
13 2018-07-05 2018-07-05
14 2018-07-14 2018-07-15
15 2018-07-14 2018-07-15
16 2018-07-20 2018-07-20
17 2018-07-21 2018-07-21
18 2018-07-10 2018-07-11
19 2018-07-12 2018-07-12
20 2018-07-12 2018-07-12

... several of the dates have been rounded up for the date_time column (rows 1, 2, 9, 14, 15, and 18). But, when I use lubridate::as_date to make the conversion...

# A tibble: 20 x 2
   date       date_time 
   <date>     <date>    
 1 2018-07-07 2018-07-07
 2 2018-07-08 2018-07-08
 3 2018-07-01 2018-07-01
 4 2018-07-02 2018-07-02
 5 2018-07-03 2018-07-03
 6 2018-07-02 2018-07-02
 7 2018-07-03 2018-07-03
 8 2018-07-08 2018-07-08
 9 2018-07-07 2018-07-07
10 2018-07-04 2018-07-04
11 2018-07-05 2018-07-05
12 2018-07-10 2018-07-10
13 2018-07-05 2018-07-05
14 2018-07-14 2018-07-14
15 2018-07-14 2018-07-14
16 2018-07-20 2018-07-20
17 2018-07-21 2018-07-21
18 2018-07-10 2018-07-10
19 2018-07-12 2018-07-12
20 2018-07-12 2018-07-12

... the dates match perfectly across columns. I've tried reading the documentation but I can't seem to figure out why as.Date is working differently than lubridate::as_date. In fact, as.Date seems to be producing incorrect conversions in several cases.

Does anybody know what's going on?


回答1:


In d$date the timezone is UTC while in d$date_time timezone has been defaulted to your default timezone. I am in EDT so here is mine:

> d$date_time

[1] "2018-07-07 23:05:00 EDT" "2018-07-09 02:25:00 EDT" "2018-07-01 06:24:00 EDT"
 [4] "2018-07-02 16:14:00 EDT" "2018-07-03 11:54:00 EDT" "2018-07-02 18:52:00 EDT"
 [7] "2018-07-03 16:15:00 EDT" "2018-07-08 04:05:00 EDT" "2018-07-07 20:41:00 EDT"
[10] "2018-07-04 11:14:00 EDT" "2018-07-05 12:30:00 EDT" "2018-07-10 11:37:00 EDT"
[13] "2018-07-05 13:50:00 EDT" "2018-07-14 20:21:00 EDT" "2018-07-15 02:54:00 EDT"
[16] "2018-07-20 12:32:00 EDT" "2018-07-21 13:47:00 EDT" "2018-07-11 02:22:00 EDT"
[19] "2018-07-12 18:25:00 EDT" "2018-07-12 11:28:00 EDT"

When you run as.Date() it will by default convert to UTC unless you specify a timezone. UTC is 4 hours ahead of EDT, thus days where the time is after 8pm will be converted to the next day, which you can see below.

> as.Date(d$date_time)
 [1] "2018-07-08" "2018-07-09" "2018-07-01" "2018-07-02" "2018-07-03" "2018-07-02" "2018-07-03"
 [8] "2018-07-08" "2018-07-08" "2018-07-04" "2018-07-05" "2018-07-10" "2018-07-05" "2018-07-15"
[15] "2018-07-15" "2018-07-20" "2018-07-21" "2018-07-11" "2018-07-12" "2018-07-12"

Lubridate as_date() specifically addresses this issue and even provides examples in its documentation.

as_date() ignores the timezone attribute, resulting in a more intuitive conversion (see examples)

That is why you see the difference.



来源:https://stackoverflow.com/questions/58528619/converting-dttm-to-date-formatting-with-as-date-and-as-date-give-different-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!