将两种时间单位格式合并为R中的一种
Merging two time unit formats into one in R
我有一个数据框,其中有一列包含描述工作时间的字符类型的列。我想将该字符向量更改为数值,以便绘制图表并推断有关它的内容。一个困难在于有两种不同的格式:
我有 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
我尝试尝试一些在“.”上分隔的拆分程序。然后以某种方式适当地重新组合它,但是如果没有'.'就会导致问题。感谢在此问题上获得我想要的结果的任何帮助,这是一个包含以分钟为单位的时间的数字向量。
我的解决方案可能有点乱七八糟,但它确实有效。但是,它不是矢量化的,对于大数据帧来说可能很慢。
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
这就是我借助 data.table
包中的 as.ITime()
函数所做的事情:
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
我有一个数据框,其中有一列包含描述工作时间的字符类型的列。我想将该字符向量更改为数值,以便绘制图表并推断有关它的内容。一个困难在于有两种不同的格式:
我有 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
我尝试尝试一些在“.”上分隔的拆分程序。然后以某种方式适当地重新组合它,但是如果没有'.'就会导致问题。感谢在此问题上获得我想要的结果的任何帮助,这是一个包含以分钟为单位的时间的数字向量。
我的解决方案可能有点乱七八糟,但它确实有效。但是,它不是矢量化的,对于大数据帧来说可能很慢。
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
这就是我借助 data.table
包中的 as.ITime()
函数所做的事情:
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