R package constructing time objects from date and hour(integer)
Asked Answered
S

4

7

I have data provided in the form of a date telling the day (format "YYYY-MM-DD", e.g. "2015-03-11" and the hours of the day numbered (0-23).

What is the most convenient way to produce time objects of the form

"2015-03-11" and hour = 0 ->  "2015-03-11 00:00"
"2015-03-11" and hour = 1 ->  "2015-03-11 01:00"
"2015-03-11" and hour = 2 ->  "2015-03-11 02:00"

I could use the Date function from Base or something from xts or timeDate. Should be easy but I am sure someone out there knows it quickly.

EDIT: the data is provided in 2 columns, one for the date and one numerical.

Subcontinent answered 13/3, 2015 at 10:35 Comment(5)
Do you have a string like "2015-03-11" and hour = 0" or is it two columns with date and numeric values form 0-23 in another?Trefor
2 columns - one date and one numeric.Subcontinent
It works the way you propose, and I added a time zone as the data are from a different time zone. Data is UTC, I am CET as.POSIXct(sprintf('%s %02d', '2015-03-11', 2), format='%Y-%m-%d %H',tz = "UTC"). Thanks!Subcontinent
When you say "time object" as output, do you want a POSIXct or a string?Endymion
Does not matter - when I have the string I can convert. Thanks!Subcontinent
R
4

Suppose we have this input:

date <- c("2015-03-11", "2015-03-12")
hour <- 2:3

then try one of these:

1) chron

library(chron)
as.chron(date) + hour/24

giving:

[1] (03/11/15 02:00:00) (03/12/15 03:00:00)

2) POSIXct. This one only uses the base of R, no packages:

as.POSIXct(date) + 3600 * hour    

giving, on my system:

[1] "2015-03-11 02:00:00 EDT" "2015-03-12 03:00:00 EDT"

If you wanted the result in the UTC time zone use:

as.POSIXct(date, tz = "UTC") + 3600 * hour  

3) lubridate

library(lubridate)
ymd(date) + hours(hour)

giving:

[1] "2015-03-11 02:00:00 UTC" "2015-03-12 03:00:00 UTC"

If you want it in the current time zone then:

ymd(date, tz = "") + hours(hour)

Note that the chron solution gives a date/time class that does not use time zones eliminating the many problems that time zones can cause. The POSIXct and lubridate solutions give the date/time in a specific time zone as shown.

Rhadamanthus answered 13/3, 2015 at 10:53 Comment(0)
N
5

You don't need an external package to do that.
If your data is in this format:

df=data.frame(date=c("2015-03-11","2015-03-11","2015-03-11"),hour=0:2)

just apply the following function:

format(as.POSIXct(df$date)+df$hour*60*60, format = "%Y-%m-%d %H:%M")
Nadler answered 13/3, 2015 at 10:43 Comment(0)
R
4

Suppose we have this input:

date <- c("2015-03-11", "2015-03-12")
hour <- 2:3

then try one of these:

1) chron

library(chron)
as.chron(date) + hour/24

giving:

[1] (03/11/15 02:00:00) (03/12/15 03:00:00)

2) POSIXct. This one only uses the base of R, no packages:

as.POSIXct(date) + 3600 * hour    

giving, on my system:

[1] "2015-03-11 02:00:00 EDT" "2015-03-12 03:00:00 EDT"

If you wanted the result in the UTC time zone use:

as.POSIXct(date, tz = "UTC") + 3600 * hour  

3) lubridate

library(lubridate)
ymd(date) + hours(hour)

giving:

[1] "2015-03-11 02:00:00 UTC" "2015-03-12 03:00:00 UTC"

If you want it in the current time zone then:

ymd(date, tz = "") + hours(hour)

Note that the chron solution gives a date/time class that does not use time zones eliminating the many problems that time zones can cause. The POSIXct and lubridate solutions give the date/time in a specific time zone as shown.

Rhadamanthus answered 13/3, 2015 at 10:53 Comment(0)
T
3

You could try

dtime <- with(df, as.POSIXct(sprintf('%s %02d', date, hour),
                    format = "%Y-%m-%d %H")) 

and then use format as in the other posts

Or

 library(lubridate)
 ymd_h(with(df, sprintf('%s %02d', date, hour)))

Or slightly more compact

ymd_h(do.call(paste, df))
Trefor answered 13/3, 2015 at 10:46 Comment(1)
@DavidArenburg For that, I have to steal your do.call :-)Trefor
B
2

Try this. You can format it without seconds afterwards using format if you wish, though I think it is preferable to keep it in POSIXct class so you can manipulate it afterwords (adding removing days, seconds, etc.)

as.POSIXct(do.call(paste, df), format = "%Y-%m-%d %H")
## [1] "2015-03-11 00:00:00 IST" "2015-03-11 01:00:00 IST" "2015-03-11 02:00:00 IST"

Though, If you insist on your exact output, here's the solution with format

format(as.POSIXct(do.call(paste, df), format = "%Y-%m-%d %H"), "%Y-%m-%d %H:%M")
## [1] "2015-03-11 00:00" "2015-03-11 01:00" "2015-03-11 02:00"

Data

df <- structure(list(V1 = structure(c(1L, 1L, 1L), .Label = "2015-03-11", class = "factor"), 
    V2 = 0:2), .Names = c("V1", "V2"), class = "data.frame", row.names = c(NA, 
-3L))
Buehrer answered 13/3, 2015 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.