我有一个带有字符向量的数据框,格式为天,小时,分钟和秒,表示为“1d 3h 2m 28s”:
> head(status[5]) Duration 1 0d 20h 46m 31s 2 2d 0h 13m 54s 3 2d 0h 13m 53s 4 0d 9h 53m 38s 5 5d 12h 17m 37s 6 0d 10h 21m 19s
我可以使用正则表达式为组件解析它,但无法想出将持续时间转换为秒的好方法.我可以将向量gsub到一个表达式,该表达式将导致秒数,但是在结果上使用eval时会遇到一个路障.
我可以做类似于推荐的here,但希望遵循正则表达式路线 – 即使它不是最有效的.我只处理解析各种小型HTML表.
status$duration <- gsub("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s.*","\\1*86400+\\2*3600+\\3*60+\\4",as.character(status[,5]),perl=TRUE)
上面创建了一个可以计算的表达式,但是当涉及到解析(text = status $duration)和后续的eval时,我遗漏了一些东西.
在perl中,我习惯于在正则表达式中使用“捕获的变量”并立即使用它们而不是仅在替换字符串中使用它们. R中是否有类似的可能性?
谢谢,由于头脑模糊,我可能会遗漏一些非常简单的东西.
下面的第一个和最后一个解决方案似乎是最简单的,但具有复杂正则表达式的解决方案更接近于perl中可能完成的工作.
原文链接:/regex/356765.html在列出解决方案本身之前,请注意,在它们中我们假设输入是tt,转换向量mult是4向量,其组件是一天,一小时,一分钟和一秒中的秒数.我们可以在注释中设置mult或如下所示计算它:
tt <- c("0d 20h 46m 31s","2d 0h 13m 54s","2d 0h 13m 53s","0d 9h 53m 38s","5d 12h 17m 37s","0d 10h 21m 19s") # mult <- c(86400,3600,60,1) mult <- rev(cumprod(rev(c(24,1))))
以下是4种方法:
1)strapply提取数字我们可以在gsubfn包中使用strapply来避免复杂的正则表达式. strapply用于提取所有数字,并将它们排列在一个矩阵中,并乘以多个字符串输出结果:
library(gsubfn) mat <- strapply(tt,"\\d+",as.numeric,simplify = TRUE) secs <- c(mult %*% mat)
这两行可以组合成一个单独的声明,但我们将保留它,如果您希望单独检查垫.
2)复杂的正则表达式的另一种可能性,也使用strapply是以下单个语句.捕获的字符串在遇到它们时被放入自由变量中,因此第一次捕获进入白天,第二次进入小时等等.这可能更接近你在perl中所做的事情:
secs <- strapply(tt,"(\\d+)d (\\d+)h (\\d+)m (\\d+)s",~ 86400 * as.numeric(day) + 3600 * as.numeric(hour) + 60 * as.numeric(minute) + as.numeric(second),simplify = TRUE)
3)复杂的正则表达式,但矢量化甚至更短:
secs <- strapply(tt,~ as.numeric(list(...)) %*% mult,simplify = TRUE)
4)strsplit,这是另一个单一的陈述答案.这个不使用strapply但是利用了这样一个事实,即字符串末尾的匹配分隔符只是被移除而没有下面的空字符串输出.有关详细信息,请参阅?strsplit.
secs <- sapply(strsplit(tt,"[dhms]"),function(x) as.numeric(x) %*% mult)
上述任何结果都是:
> secs [1] 74791 173634 173633 35618 476257 37279