I have a data frame of two columns "start" and "end" in HH:MM:SS format.
I wanted to calculate duration between start and end using difftime function
It always gives back this error: Error in as.POSIXct.numeric(time1) : 'origin' must be supplied
I read many posts but none seemed to work for me.
Loading packages
library(dplyr)
library(tidyverse)
library(lubridate)
I removed hours to deal with minutes and seconds only
get_time <- function(x){str_sub(x, start = -5) %>% ms()}
df <- df %>% mutate(start = get_time(start)) %>%
mutate(end = get_time(end))
Class of objects
class(df$start)
gives:
[1] "Period"
attr(,"package")
[1] "lubridate"
start end
26M 22S 26M 23S
26M 25S 26M 37S
29M 47S 30M 13S
I calculated duration using difftime function
df$duration <- with(df, difftime(end, start, units="secs"))
gives error:
Error in as.POSIXct.numeric(time1) : 'origin' must be supplied
I used subtraction operator, it worked fine except for 3rd row when minutes are different, it gave wrong answer.
start end duration
26M 22S 26M 23S 1S
26M 25S 26M 37S 12S
29M 47S 30M 13S 1M -34S
Amendment
The accepted response works perfectly fine, except that it returns an error: Error in mtx1[3, ] : incorrect number of dimensions whenever applied to the second two columns "start2" and "end2" that I have in the same data frame.
sample from my df
df <- structure(list(item = c("manatee", "manatee", "pile", "pile"), prestart = new("Period", .Data = c(22,
25, 41, 49), year = c(0, 0, 0, 0), month = c(0,
0, 0, 0), day = c(0, 0, 0, 0), hour = c(0, 0, 0,
0), minute = c(26, 26, 26, 26)), preend = new("Period",
.Data = c(23, 37, 48, 50), year = c(0, 0, 0, 0), month = c(0, 0, 0, 0), day = c(0, 0, 0, 0
), hour = c(0, 0, 0, 0), minute = c(26, 26, 26, 26)), poststart = new("Period", .Data = c(23, 41, 50,
54), year = c(0, 0, 0, 0), month = c(0, 0, 0, 0), day = c(0, 0, 0, 0), hour = c(0, 0, 0, 0),
minute = c(26, 26, 26, 26)), postend = new("Period",
.Data = c(37, 48, 52, 22), year = c(0, 0, 0, 0), month = c(0, 0, 0, 0), day = c(0, 0, 0, 0
), hour = c(0, 0, 0, 0), minute = c(26, 26, 26, 27))), row.names = c(NA, -6L), class = c("tbl_df", "tbl",
"data.frame"))
Organising data in minutes and seconds only (remove hours)
get_time <- function(x){str_sub(x, start = -5) %>% ms()}
df <- df %>% mutate(prestart = get_time(prestart)) %>%
mutate(preend = get_time(preend)) %>%
mutate(poststart = get_time(poststart)) %>%
mutate(postend = get_time(postend))