If I have a vector of dates and hours such as...
c("2016-03-15 13","2016-03-16 23","2016-03-17 06","2016-03-18 15","2016-03-19 08","2016-03-20 21")
Can I find the number of hours that pass between each timestamp? I looked into difftime but it requires 2 vectors.
We can do this after converting to 'DateTime' class using lubridate, then get the difference in 'hour' between adjacent elements using difftime by passing two vectors after removing the last and first observation in the vector
library(lubridate)
v2 <- ymd_h(v1)
Or a base R option is as.POSIXct
v2 <- as.POSIXct(v1, format = "%Y-%m-%d %H")
and then do the difftime
difftime(v2[-length(v2)], v2[-1], unit = "hour")
data
v1 <- c("2016-03-15 13","2016-03-16 23","2016-03-17 06",
"2016-03-18 15","2016-03-19 08","2016-03-20 21")
You can do this by using strptime() function.
Try something like this.
data <- c("2016-03-15 13","2016-03-16 23","2016-03-17 06","2016-03-18 15","2016-03-19 08","2016-03-20 21")
datevec <- strptime(data,"%Y-%m-%d %H")
difftime(datevec[-length(datevec)],datevec[-1],units="hours")
Here is the output.
> difftime(datevec[-length(datevec)],datevec[-1],units="hours")
Time differences in hours
[1] -34 -7 -33 -17 -37
Related
I have a problem in R that is killing me! Can you help me?
I found a question in StackOverflow that gave me a very good explanation.
Here is the link: How to parse milliseconds?
I was able to implement the following code that works very well.
z2 <- strptime("10/2/20 11:16:17.682", "%d/%m/%y %H:%M:%OS")
z1 <- strptime("10/2/20 11:16:16.683", "%d/%m/%y %H:%M:%OS")
When I calculate z2-z1, I get
Time difference of 0.9989998 secs
Similarly, when I use
z3 <- strptime("130 11:16:16.683", "%j %H:%M:%OS")
z4 <- strptime("130 11:16:18.682", "%j %H:%M:%OS")
When I calculate z4-z3, I get
Time difference of 1.999 secs
What is my problem?
The first column has the format 130 18:25:50.408, with millions of rows!!!
The second column has the format 2020 130 18:25:51.357 that is like the first column but has the year 2020.
The first column is also from 2020, but as the year is not there R uses the current year.
First question,
How can I substract both columns? I know how to substract columns.
What I do not know is to subtract these two times.
For example, second time is 2020 130 18:25:51.357
and first time is 130 18:25:50.408
I guess that I can do it programmatically converting it to a string, and eliminating the 2020. However, I am hoping that a quicker solution is available using base R or the lubridate package.
Second question,
"%j %H:%M:%OS" is the format for 130 11:16:16.683
What is the format for 2020 130 18:25:51.357?
As explained before this is working very well:
z3 <- strptime("130 11:16:16.683", "%j %H:%M:%OS")
But, this is NOT working.
z7 <- strptime("2020 130 11:16:16.683", "%y %j %H:%M:%OS")
UPDATE 1
I solved the second question!
However, I have not figured out yet the first question.
For the second question, the mistake in the format was that instead of %y, I need to write %Y with upper case.
Here is one example:
later <- strptime("2020 130 11:16:17.683", "%Y %j %H:%M:%OS")
earlier <- strptime("2020 130 11:16:16.684", "%Y %j %H:%M:%OS")
difftime(later,earlier,units="secs")
The R results is:
Time difference of 0.9990001 secs
UPDATE 2
At this point, what is pending is the following:
I need to substract two times that were made the same day on 2020.
The second time does have the year, the first time does not.
later <- strptime("2020 130 11:16:17.683", "%Y %j %H:%M:%OS")
earlier <- strptime("130 11:16:16.684", "%j %H:%M:%OS")
difftime(later,earlier,units="secs")
R produces the following result:
Time difference of -31622399 secs
Why? As we are on 2021, R formats the vector earlier as the current year, 2021 because the year is not there.
My columns has millions of rows.
At this point, my guess is that I would need to add 2020 with a concatenation or something like that. Is there any other method?
Thank you for your help!
Your object z2 is a POSIX list object. What this means is that it is a list of the time elements of your time.
print.default(z2)
# $sec
# [1] 17.682
#
# $min
# [1] 16
#
# $hour
# [1] 11
#
# $mday
# [1] 10
#
# $mon
# [1] 1
#
# $year
# [1] 120
#
# $wday
# [1] 1
#
# $yday
# [1] 40
#
# $isdst
# [1] 0
#
# $zone
# [1] "GMT"
#
# $gmtoff
# [1] NA
#
# attr(,"class")
# [1] "POSIXlt" "POSIXt"
When you do a subtraction, z2 - z1 R dispatches this operation to a function called -.POSIXt, which itself calls difftime. This function converts z2 to a POSIX count object. What this means is that it gets converted to a count of seconds since the beginning of the epoch, by default "1970-01-01".
options("digits" = 16)
print.default(as.POSIXct(z2))
# [1] 1581333377.682
# attr(,"class")
# [1] "POSIXct" "POSIXt"
# attr(,"tzone")
# [1] ""
difftime(z2, z1)
# Time difference of 0.9989998340606689 secs
R, like most software, works with double precision numerics. This means that arithmetic is imprecise, although approximately true. Most software will try to hide this imprecision by reducing the number of digits shown. That said, different numbers will give you different imprecision, so you might prefer referring directly to the list element of z2.
print.default(z2$sec - z1$sec)
# [1] 0.9989999999999988
You could therefore apply the time difference using your favourite data.frame tools.
options("digits" = 6)
# character columns
df1 <- data.frame(
col1 = c("10/2/20 11:16:17.682", "10/2/20 11:16:16.683"),
col2 = c("130 11:16:16.683", "130 11:16:18.682"),
stringsAsFactors = FALSE)
library(dplyr)
# convert columns to POSIXlt
df2 <- mutate(df1,
col1 = strptime(col1, "%d/%m/%y %H:%M:%OS"),
col2 = strptime(stringr::str_c("2020 ", col2), "%Y %j %H:%M:%OS"),
diff_days = unclass(difftime(col2, col1, units = "days")))
df2
# col1 col2 diff_days
# 1 2020-02-10 11:16:17 2020-05-09 11:16:16 88.9583
# 2 2020-02-10 11:16:16 2020-05-09 11:16:18 88.9584
I have a data.table dt which have many records .
It have two columns datetime1, with value as "2017-04-19 09:54:00" of class POSIXct
another column have time values like "7.97" of class numeric. It is for the same date.
I want to calculate a difference in the time in minutes. how can I do it in R
Try this
time1 <- as.POSIXct('2017-04-19 09:54:00')
time2 <- as.POSIXct('2017-04-19 00:00:00') + 3600*7.97
60*as.numeric(time1 - time2)
You can use functions of lubridate to extract hour, minute, and second of the POSIXct and then calculate the difference.
library(lubridate)
x = as.POSIXct("2017-04-19 09:54:00", tz = "UTC")
hour(x) * 60 + minute(x) + second(x)/60 - 7.97 * 60
#[1] 115.8
I have a time variable say x. The class of my vector is a character
x <- c("06:59:20","19:13:31", "06:08:02", "00:25:14", "19:25:01" ,"21:21:44"
,"19:04:25" , "19:43:31", "16:00:13", "05:15:37", "05:52:16", "21:47:51", "06:33:36"
,"06:59:29" ,"20:06:04", "05:08:15", "20:09:51", "21:52:25", "19:07:22", "19:37:26")
I convert it into a times object by using the below approach
x_posix <- as.POSIXct(x, format = "%H:%M:%S")
x<- strftime(x_posix, format="%H:%M:%S")
x <- times(x)
[1] 06:59:20 19:13:31 06:08:02 00:25:14 19:25:01 21:21:44 19:04:25 19:43:31 16:00:13 05:15:37 05:52:16 21:47:51 06:33:36 06:59:29 20:06:04
[16] 05:08:15 20:09:51 21:52:25 19:07:22 19:37:26
Now I want to find out how many values are lie between any time interval.
Suppose If I want to find out that how many values are between 6 to 7 then I want to include all those values that are in between 6:00:00(including 6:00:00) and up to all values that are less than or equal to 6:59:59.
Is there any way in R to accomplish this task ?
We can use
library(chron)
sum(x1 >= times("06:00:00") & x1 < times("07:00:00"))
#[1] 4
data
x1 <- times(x)
I have a vector "Time.Training" in the format hours:minutes:seconds (e.g.
Time.Training <- c("1:00:00", "0:45:00", "0:30:00", "1:30:00")
I would like to convert this into minutes in the format:
Time.Training.Minutes <- c(60, 45, 30, 90)
I'm wondering if someone has a straightforward method of doing this in R.
Many thanks.
Matt
Using lubridate:
Time.Training<- c("1:00:00", "0:45:00", "0:30:00", "1:30:00")
library(lubridate)
res <- hms(Time.Training) # format to 'hours:minutes:seconds'
hour(res)*60 + minute(res) # convert hours to minutes, and add minutes
## [1] 60 45 30 90
Try this. We basically converting to POSIXlt class first by pasting a real date to the vector using the Sys.Date() function (because there is no hour class in base R) and then using hour and min arguments in order to achieve the output
Res <- as.POSIXlt(paste(Sys.Date(), Time.Training))
Res$hour*60 + Res$min
## [1] 60 45 30 90
Use as.difftime:
> Time.Training<- c("1:00:00", "0:45:00", "0:30:00", "1:30:00")
> strtoi(as.difftime(Time.Training, format = "%H:%M:%S", units = "mins"))
[1] 60 45 30 90
Here are some alternatives:
1) The chron package has a "times" class in which 1 unit is a day and there are 60 * 24 minutes in a day so:
library(chron)
60 * 24 * as.numeric(times(Time.Training))
giving:
[1] 60 45 30 90
1a) Another approach using chron is the following (giving the same answer):
library(chron)
ch <- times(Time.training)
60 * hours(ch) + minutes(ch)
2) Here is an approach using read.table and matrix/vector multiplication. No packages are needed:
c(as.matrix(read.table(text = Time.Training, sep = ":")) %*% c(60, 1, 1/60))
(Using "POSIXlt" is probably the most straight-forward approach without packages but another answer already provides that.)
Taking the hour column from the date time column and create a new cloumn hour and give only hour data in that column 2011-01-01 00:00:01
Ans :
bikeshare$hour<-sapply(bikeshare$datetime,function(x){format(x,"%H")})
I am importing some data from NOAA and it has dates and times in separate columns. I searched for an elegant way to append a single datetime column in my R dataframe but was unable. I found a stack exchange question about the inverse but not this one. Is there a simple as.Date command I could run? I am simply using read.table for a downloaded text file and it imports just find.
Buoy data is here:
http://www.ndbc.noaa.gov/data/realtime2/51202.txt
>yr mo dy hr mn degT m.s m.s.1 m sec sec.1 degT.1 hPa degC degC.1 degC.2 nmi hPa.1 ft
>2012 1 16 3 55 MM MM MM 1.4 10 7.2 339 MM MM 23.9 MM MM MM MM
You can use ISOdatetime, which is just a simple wrapper to as.POSIXct. Make sure to specify the sec argument as zero.
Data$timestamp <- with(Data, ISOdatetime(YY,MM,DD,hh,mm,0))
Yep, you want to paste the date time columns together and then coerce that full string to a date time object.
dat <- within(dat, datetime <- as.POSIXlt(paste(yr, mo, dy, hr, mn),
format = "%Y %m %d %H %M"))
assuming dat is the object containing the buoy data. This adds a new columns that is a "POSIXlt" class object or you could use as.POSIXct() if you prefer the other format.
Or, having looked at the file so can use their column names:
dat <- within(dat, datetime <- as.POSIXlt(paste(YY, MM, DD, hh, mm),
format = "%Y %m %d %H %M"))