1

I have two data frames with time data every 15 minutes but one starts precisely on time (0:00, 0:15, 0:30, 0:45, etc.) and one starts slightly off (0:03, 0:18, 0:33, 0:48, etc). I would like to round the slightly off one to the nearest 15 minutes interval so that I may later merge the data frames so that the data corresponding to those times are in the same rows. The data is in 24 hour time and, as an example, in the format of:

Time
0:00
0:15
0:30
0:45
1:00

I have tried the code below but r returns the error:

library(lubridate)
p_data <- read.csv("Filter12.csv", header = TRUE)
p_data$Time <- round_date(p_data$Time, "15 mins")

Error in UseMethod("reclass_date", orig) :
no applicable method for 'reclass_date' applied to an object of class "character"
In addition: Warning message: All formats failed to parse. No formats found.

I then tried converting the time column from character to numeric but recieved the error:

p_data$Time <- as.numeric(p_data$Time)
Warning message:
NAs introduced by coercion

I am very new to r (just started learning this week) so I apologize if this is due to a lack of common knowledge.

tarrikq
  • 13
  • 3
  • 2
    Looks like you need to convert the character string that is representing a date-time to an acutal date-time object first... You could improve your chance of finding help here by adding a [minimal reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610#5963610). Adding a MRE and an example of the desired output (in code form, not tables and pictures) makes it much easier for others to find and test a answer to your question. That way you can help others to help you! – dario May 19 '21 at 14:11
  • You were right! I was able to round using one of the answers after I converted the time data from character to date-time. Also Thank you for the information on MRE, I will be sure to add that to any future questions I have. – tarrikq May 19 '21 at 18:16

2 Answers2

4

Here an approach with lubridate. We first generate an arbitrary data set and then round it to 15minutes:

library(lubridate)
x <- seq(as.POSIXct("2021-05-19 10:00"), as.POSIXct("2021-05-19 11:00"), 240)
x

round_date(x, unit="15 mins")

Edit: here the same idea with minutes only. We use a fake date, append the time, round it to 15min and extract minutes only:

library(lubridate)
x <- c("0:03", "0:18", "0:33", "0:48")
format(round_date(as.POSIXct(paste("1900-01-01 ", x)), unit="15 mins"), "%M")
tpetzoldt
  • 5,338
  • 2
  • 12
  • 29
3

1) times Convert to times class, round it and then convert back to character. The hour must be less than 24 but that seems to be the case in the question.

library(chron)
x <- c("0:03", "0:18", "0:33", "0:48") # input

sub(":..$", "", round(times(paste0(x, ":00")), "00:15:00"))
## [1] "00:00" "00:15" "00:30" "00:45"

2) Base R Convert to difftime and then numeric minutes, round it and finally display in required form.

mins <- 15 * round(as.double(as.difftime(x, format = "%H:%M"), "mins") / 15)
format(as.POSIXct(60 * mins, origin = "1970-01-01", tz = "GMT"), "%H:%M") ###
## [1] "00:00" "00:15" "00:30" "00:45"

2a) A base R solution not using difftime or POSIXct is:

mins <- with(read.table(text = x, sep = ":"), 15 * round((60 * V1 + V2) / 15))
sprintf("%02d:%02d", mins %/% 60, mins %% 60)
## [1] "00:00" "00:15" "00:30" "00:45"
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341