1

Trying to convert the following durations into seconds

x <- "1005d 16h 09m 57s"
x1 <- "16h 09m 57s"
x2 <- "06h 09m 57s"
x3 <- "09m 57s"
x4 <- "57s"

I've modified the answer from Jthorpe in this post Convert factor of format Hh Mm Ss to time duration.

days <- as.numeric(gsub('^*([0-9]+)d.*$','\\1',x3))
hours <- as.numeric(gsub('^.*([0-9][0-9])h.*$','\\1',x3))
minutes <- as.numeric(gsub('^.*([0-9][0-9])m.*$','\\1',x4))
seconds <- as.numeric(gsub('^.*([0-9][0-9])s.*$','\\1',x4))
duration_seconds <- seconds + 60*minutes + 60*60*hours + 24*60*60*days

However, this is only working with x, but not x1-x4. Now, I know I can probably use if logic to get around the issue, but is there a better way?

Thanks in advance.

Community
  • 1
  • 1
woshishui
  • 1,906
  • 2
  • 15
  • 22

2 Answers2

4

We can change the space character (\\s+) with + using gsub, then we can replace 'd', 'h', 'm', 's' with gsubfn and loop through the output and evaluate the string.

library(gsubfn)
v2 <- gsubfn("[a-z]", list(d="*24*60*60", h = "*60*60", m = "*60",
        s="*1"), gsub("\\s+", "+", v1))
unname(sapply(v2, function(x) eval(parse(text=x))))
#[1] 86890197    58197    22197      597       57

data

 v1 <- c(x, x1, x2, x3, x4)
akrun
  • 874,273
  • 37
  • 540
  • 662
  • 1
    @ akrun, WOW, I LOVE this. I'll spend sometime trying to get my head around the second part. haha – woshishui May 04 '16 at 05:43
  • 1
    that is a brilliant solution to a common and ugly problem. – MMerry May 04 '16 at 06:10
  • @ akrun, I got myself into another trouble with this approach. I'm using data frame df, then df$v3 <- unname(sapply(v2,....)), df$v3 was created as a list. I tried to use df$vs <-as.data.frame(uname(...)), it gives the following error, "arguements imply differeing number of rows: 1,0". Any suggestion? – woshishui May 04 '16 at 07:09
  • @woshishui It must be because there are more than one elements that result as a `list` output. Can you show a small data that shows the problem? What is the output from 'v2'? – akrun May 04 '16 at 07:22
  • 1
    @ akrun. the list is caused by blank entries in duration (change x4<-""), unname(sapply) put this into a list. It can be resolved by ifelse(duration=="", "0", gsubfn(...)). Thanks again. – woshishui May 04 '16 at 12:44
2

Use:

ifelse(is.na(your_exp),0)

So that whenever na is the output of your expression it becomes 0.

Eg:

days <- ifelse(is.na(as.numeric(gsub('^*([0-9]+)d.*$','\\1',x1))),0)
hours <- ifelse(is.na(as.numeric(gsub('^.*([0-9][0-9])h.*$','\\1',x1))),0)
minutes <- ifelse(is.na(as.numeric(gsub('^.*([0-9][0-9])m.*$','\\1',x1))),0)
seconds <- ifelse(is.na(as.numeric(gsub('^.*([0-9][0-9])s.*$','\\1',x1))),0)

Output:(after duration_seconds <- seconds + 60*minutes + 60*60*hours + 24*60*60*days)

> duration_seconds
[1] 58197
Ani Menon
  • 27,209
  • 16
  • 105
  • 126