如何将不同单位的向量解析为毫秒?

sta*_*ant 2 r

我有一个包含自纪元以来的时间的文件.问题是那些时间写得像[0-9]{3}[ms|s|m]

times = c('001ms','023ms','011s','923s','001m','012m','111m')
Run Code Online (Sandbox Code Playgroud)

我希望能够将其转换为"毫秒数"(或数字或秒或分钟......).我会得到类似的东西:

c(1, 23, 11000, 923000, ...)
Run Code Online (Sandbox Code Playgroud)

是否有一些功能可以让我有效地解析这些时间?

Ric*_*ven 5

您可以使用查找向量.

## create a conversion lookup vector
converter <- c(ms = 1, s = 1e3, m = 1e3*60)
## get the units from the 'times' vector
units <- sub("[^a-z]+", "", times)
## get the numerics from the 'times' and convert them
as.vector(converter[units]) * as.numeric(sub("[a-z]+$", "", times))
# [1]     1      23   11000  923000   60000  720000 6660000 
Run Code Online (Sandbox Code Playgroud)

as.vector()仅用于删除转换器查找遗留的名称.上面的代码为您提供毫秒转换.要转换为秒,只需将转换器除以1000即可.

as.vector((converter/1e3)[units]) * as.numeric(sub("[a-z]+$", "", times))
# [1]    0.001    0.023   11.000  923.000   60.000  720.000 6660.000
Run Code Online (Sandbox Code Playgroud)

当然,您也可以使用s = 1转换器向量,然后转向其他方式.

如果你想要一个功能,你可以用上面的代码自己动手.包括units参数,我们可以指定我们希望单位在结果中的内容.

convert <- function(x, units = "ms") {
    conv <- c(ms = 1, s = 1e3, m = 1e3*60)
    div <- if(units == "s") 1e3 else if(units == "m") 1e3*60 else 1
    as.vector((conv/div)[sub("[^a-z]+", "", x)] * as.numeric(sub("[a-z]+$", "", x)))
}
## milliseconds
convert(times)
# [1]       1      23   11000  923000   60000  720000 6660000
## seconds
convert(times, "s")
# [1]    0.001    0.023   11.000  923.000   60.000  720.000 6660.000
## minutes
convert(times, "m")
# [1] 1.666667e-05 3.833333e-04 1.833333e-01 1.538333e+01 1.000000e+00 1.200000e+01 1.110000e+02
Run Code Online (Sandbox Code Playgroud)

它也适用于十进制值,并且在效率方面也表现得相当好.

convert(c("10.45ms", "1.32s"))
# [1]   10.45 1320.00
convert(c("10.45ms", "1.32s"), "s")
# [1] 0.01045 1.32000

x <- rep(times, 1e4)
library(microbenchmark)
microbenchmark(ms = convert(x), s = convert(x, "s"), m = convert(x, "m"))
# Unit: milliseconds
#  expr      min       lq     mean   median       uq      max neval
#    ms 106.9894 108.7634 111.6799 109.1281 110.5011 167.4422   100
#     s 107.0723 108.8816 113.4689 109.1957 110.6959 163.7447   100
#     m 107.1299 108.9235 113.6086 109.2279 110.9650 164.1910   100
Run Code Online (Sandbox Code Playgroud)