将两种时间单位格式合并为R中的一种

时间:2018-06-15 12:58:21

标签: r time split format duration

我有一个数据框,其中的列包含描述工作时间的字符类型的列。我想将该字符向量更改为数值,以便绘制图并推断出它。一个困难在于有两种不同的格式:

我有01.09:55:00表示1天,9小时,55分钟和0秒,或者如果没有达到一整天,04:30:00表示4小时30分0秒。如果它更容易,将不会超过100天。小时,分钟,秒始终存在,但不是天数,分离是不同的。

我已经可以使用它来处理第二种格式,以便在几分钟内获得时间:

MyData $ Working_Time_Total = strptime(MyData $ Working_Time_Total,format =“%H:%M:%S”) MyData $ Working_Time_Total =(MyData $ Working_Time_Total $ sec + MyData $ Working_Time_Total $ min * 60 + MyData $ Working_Time_Total $ hour * 3600)/ 60

我试图尝试一些分离程序,分开'。'然后以某种方式重新组合它,但是如果没有'。'则会导致问题。我很感激在这个问题上有任何帮助来获得我想要的结果,这是一个包含以分钟为单位的时间的数字向量。

2 个答案:

答案 0 :(得分:1)

这是我在as.ITime()包中使用data.table函数的帮助:

times <- c("04:30:00", "01.09:55:00")

library(data.table)
cols <- c("days", "hms")
as.data.table(times)[
  times %like% "[.]", (cols) := tstrsplit(times, "[.]")][
  is.na(days), (cols) := .( "0", times)][
    , as.integer(days) * 60 * 24 + as.integer(as.ITime(hms, "%H:%M:%S")) / 60][]
[1]  270 2035

基准

# create benchmark data
times0 <- CJ(c("", sprintf("%02i.", 1:99)), 1:24, 1:60)[, sprintf("%s%02i:%02i:00", V1, V2, V3)]

# run benchmarks
microbenchmark::microbenchmark(
  apitsch = {
    times <- copy(times0)
    for (i in 1:length(times)){
      # for format without days:
      if (nchar(times[i]) == 8){
        tmp <- as.numeric(unlist(strsplit(times[i], split = ":")))
        times[i] <- tmp[1] * 60 + tmp[2] + tmp[3] * 1/60 
      } else { # for format including days:
        tmp <- c(unlist(strsplit(times[i], split = "[.]")))
        tmp <- c(tmp[1], unlist(strsplit(tmp[2], split = ":")))
        tmp <- as.numeric(tmp)
        times[i] <- tmp[1] * 24 * 60 + tmp[2] * 60 + tmp[3] + tmp[4] * 1/60
      }
    }
    times
  },
  uwe = {
    times <- copy(times0)
    cols <- c("days", "hms")
    as.data.table(times)[
      times %like% "[.]", (cols) := tstrsplit(times, "[.]")][
        is.na(days), (cols) := .( "0", times)][
          , as.integer(days) * 60 * 24 + as.integer(as.ITime(hms, "%H:%M:%S")) / 60][]
  },
  times = 11L
  )
Unit: milliseconds
    expr       min        lq      mean    median        uq      max neval cld
 apitsch 3485.6488 3561.5639 3708.8017 3631.2264 3747.1996 4288.368    11   b
     uwe  493.0976  497.6782  582.6732  540.5967  643.0875  773.587    11  a

答案 1 :(得分:0)

我的解决方案可能有点像黑客,但它确实有效。但是,它没有矢量化,对于大数据帧来说可能会很慢。

times <- c("04:30:00", "01.09:55:00")

# loop over "times" // rows of a column vector
for (i in 1:length(times)){
  # for format without days:
  if (nchar(times[i]) == 8){
    tmp <- as.numeric(unlist(strsplit(times[i], split = ":")))
    times[i] <- tmp[1] * 60 + tmp[2] + tmp[3] * 1/60 
  } else { # for format including days:
    tmp <- c(unlist(strsplit(times[i], split = "[.]")))
    tmp <- c(tmp[1], unlist(strsplit(tmp[2], split = ":")))
    tmp <- as.numeric(tmp)
    times[i] <- tmp[1] * 24 * 60 + tmp[2] * 60 + tmp[3] + tmp[4] * 1/60
  }
}

print(as.numeric(times))
# [1] 270  2035