I have a column of time
a = times('00:00:00', '00:15:00', '01:45:00', '23:45:00')
And I would like to give them an index based on a 15 min interval. So for example, 00:00:00 will be 1, 00:15:00 will be 2, and 23:45:00 will be 96 as there are ninety-six 15 min intervals in a 24hr period.
So the result I want is:
1 2 8 96
Another fun idea,
cumsum(c(1, diff(strptime(a, format = "%T")) / 15))
#[1] 1 2 8 96
We can use cut with breaks of "15 mins" after converting a to time object and convert the levels to numeric.
as.integer(cut(strptime(a, format = "%T"), breaks = "15 mins"))
#[1] 1 2 8 96
Same would also work with as.POSIXct
as.integer(cut(as.POSIXct(a, format = "%T"), breaks = "15 mins"))
Using lubridate we can convert to seconds and do
library(lubridate)
period_to_seconds(hms(a))/(15*60) + 1
Or with minute
minute(as.period(hms(a), "minutes"))/15 + 1
You might need ceiling/floor based on the time duration to round values.
data
a <- c('00:00:00', '00:15:00', '01:45:00', '23:45:00')
I'm trying to calculate the difference-in-years between 2 dates.
time1 <- as.Date(x = "2017-02-14",
format = "%Y-%m-%d",
origin = "",
tz = "")
time2 <- as.Date(x = "1972-02-17",
format = "%Y-%m-%d",
origin = "",
tz = "")
as.integer(x = difftime(time1 = time1,
time2 = time2,
tz = "",
units = "days")) / 365
According to the above code, the difference-in-years is about 45.02466.
A glance at the 2 dates confirms that the difference-in-years is close to, but less than, 45.
The difference-in-years value should begin with 44.
Why is difftime inflating the number of years by 1?
Probably this happens since you divide by 365 days, whereas at least 44/4 = 11 years had a duration of 366 days. You could consider to divide by 365.25, which is a more correct average duration of a year.
Also, you might like to look up the lubridate package to see the interval of how many years have passed between two dates
library(lubridate)
> time1 <- as.Date(x = "2017-02-14",
+ format = "%Y-%m-%d",
+ origin = "",
+ tz = "")
>
> time2 <- as.Date(x = "1972-02-17",
+ format = "%Y-%m-%d",
+ origin = "",
+ tz = "")
>
>
> interval(time2, time1) %/% years(1)
[1] 44
There are an average of 365.25 days in a year due to leap years -- could be slightly different if the number of years is not a multiple of 4 but this is a reasonable long term average to use. By using 365 instead this inflated the answer in the question.
time1 <- as.Date("2017-02-14")
time2 <- as.Date("1972-02-17")
as.numeric(time1 - time2) / 365.25
## [1] 44.99384
Standardized years
If you want to be really exact about leap years there were 12 leap days between time1 and time2
tt <- seq(time2, time1, by = "day")
no_leap_days <- sum(format(tt, "%m-%d") == "02-29")
no_leap_days
## [1] 12
so another way to do this is to calculate the number of days between the two dates, subtract the number of leap days effectively standardizing every year to 365 days and then divide by 365:
as.numeric(time1 - time2 - no_leap_days) / 365
## [1] 44.99178
Note
Note that "Date" class does not have a time zone, origin is only used in as.Date if the argument is numeric and the format used in the question is the default format so format is not needed.
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
This question already has an answer here:
Split time series data into time intervals (say an hour) and then plot the count
(1 answer)
Closed 7 years ago.
Date,Time,Lots,Status
"10-28-15","00:04:50","13-09","1111111110000000"
"10-28-15","00:04:50","13-10","1111100000000000"
"10-28-15","00:04:50","13-11","1111111011100000"
"10-28-15","00:04:50","13-12","1111011111000000"
"10-28-15","00:04:57","13-13","1111111111000000"
"10-28-15","00:04:57","13-14","1111111111110000"
"10-28-15","00:04:57","13-15","1111111100000000"
"10-28-15","00:04:57","13-16","1111111111000000"
"10-28-15","00:05:04","13-17","1111111110000000"
"10-28-15","00:05:04","13-18","1111101100000000"
"10-28-15","00:05:04","13-19","1111111111100000"
"10-28-15","00:05:04","13-20","1111111111100000"
"10-28-15","00:05:11","13-21","1111110100000000"
"10-28-15","00:05:11","13-22","1000011111100000"
"10-28-15","00:05:11","13-23","1101011111110000"
"10-28-15","00:05:11","13-24","1111111111000000"
"10-28-15","00:05:19","13-25","1011000000000000"
"10-28-15","00:05:19","13-26","0000000000000000"
"10-28-15","00:05:19","13-27","1111011110000000"
"10-28-15","00:05:19","13-28","1010000000000000"
say dfrm above "sample", I need to convert the time into time interval of 15 minutes. How do I do that? Eg: I have 4 intervals for every hour. 00:04:50 will go into 00:04:45 - 00:04:50. Thanks!
I have tried using:
format(as.POSIXlt(as.POSIXct('2000-1-1', "UTC") + round(as.numeric(sample$V3)/300)*300), format = "%H:%M:%S")
I hope I understood your question correctly, but I think you could do it like this:
# example data frame:
myDat <- data.frame(date = rep("2010-08-15",30),
time = sprintf("%02i:%02i:%02i",rep(12:14,each=10),rep(c(0,15,16,29:31,44:45,59,1),3),sample(1:59)[30]))
#produce a datetime variable
myDat$datetime <- strptime(x = paste(myDat$date,myDat$time),format = "%Y-%m-%d %H:%M:%S")
# extract the minutes
myDat$min <- as.integer(as.character(myDat$datetime,format="%M"))
# find the interval to put them in
myDat$ival <- findInterval(myDat$min,c(15,30,45,60)); myDat$ival <- factor(myDat$ival)
levels(myDat$ival) <- c("00","15","30","45")
# concatenate minute interval and hour
myDat$timeIval <- sprintf("%s:%s:00",as.character(myDat$datetime,format="%H"),myDat$ival)
myDat[order(myDat$datetime),]
I'd first convert the data to POSIXct
time <- as.POSIXct(
strptime(paste0(df$column1, " ", df$column2), format="%m-%d-%y %H:%M:%S")
)
and then use seq.POSIXct and cut to generate a factor variable for the 15 min intervals.
interval <- cut(
time,
breaks = seq(starttime, endtime, as.difftime(15, units="mins))
)
You may want to add -Inf or Inf to the breaks to avoid generating NA values.
Inside a function a need to convert some number, in general in range of 20 to 200, in to difftime and show via format as expected time needed to finish.
as.difftime has got a useful units="auto" so it will use "sec" say for 20 secs and "mins" for 60+ secs...
But it says also
> as.difftime(100, units="auto")
Error in as.difftime(100, units = "auto") :
need explicit units for numeric conversion
How can I avoid that?
EDIT: Current workaround
> (Sys.time()+100)-Sys.time()
Time difference of 1.666667 mins
Is lubridate an alternative?
library(lubridate)
new_difftime(second = 20)
# Time difference of 20 secs
new_difftime(second = 60)
# Time difference of 1 mins
new_difftime(second = 240)
# Time difference of 4 mins
new_difftime(second = 1000000)
# Time difference of 11.57407 days
# new_difftime creates an object of same class as as.difftime does.
class(as.difftime(20, units = "secs"))
# [1] "difftime"
class(new_difftime(second = 20))
# [1] "difftime"
It is also possible to specify input values of several units. E.g. from ?new_difftime
new_difftime(second = 3, minute = 1.5, hour = 2, day = 6, week = 1)
# Time difference of 13.08441 days