在R中将无前置零的H/M/S格式转换为HH:MM:SS或时间对象
时间格式转换与解析问题
问题背景
数据被从标准的HH:MM:SS格式改成了无前置零的H/M/S格式:
- 示例1:
10:32:20→10H 32M 20S - 示例2:
7:30:04→7H 30M 4S
想搞清楚这种格式是不是某个R包的标准格式,同时需要将其转换回HH:MM:SS格式,或者直接解析为时间对象。
最初只注意到秒数缺失前置零,写了如下代码,但处理不全面:
# turn e.g. 10H 12M 30S -> 10:12:30 df$Time = gsub(" ", "", c(df$Time)) df$Time = gsub("[^0-9]", ":", c(df$Time)) df$Time = gsub("::", ":", c(df$Time)) df$Time = substring(df$Time,1,nchar(df$Time) - 1) for (i in seq_along(df$Time)) { if (nchar(df$Time[i]) == 7) { gsub("([0-9]*$)", paste(0, str_sub(df$Time[i], start=7), sep=""), df$Time[i]) } }
解决方案
方法1:正则拆分+补零转换为HH:MM:SS
用正则表达式提取时、分、秒的数值,再通过sprintf统一补零到两位,最后拼接成目标格式:
library(stringr) # 定义转换函数 convert_time <- function(time_str) { # 提取时、分、秒的数字 hours <- str_extract(time_str, "\\d+(?=H)") mins <- str_extract(time_str, "\\d+(?=M)") secs <- str_extract(time_str, "\\d+(?=S)") # 补零并拼接 sprintf("%02d:%02d:%02d", as.integer(hours), as.integer(mins), as.integer(secs)) } # 测试示例 test_times <- c("10H 32M 20S", "7H 30M 4S", "1H 2M 3S") sapply(test_times, convert_time) # 输出: # "10H 32M 20S" "7H 30M 4S" "1H 2M 3S" # "10:32:20" "07:30:04" "01:02:03"
方法2:直接解析为时间对象(用lubridate包)
如果不需要转成字符串格式,而是要解析为时间间隔对象,可以用lubridate包的时间组件函数:
library(lubridate) library(stringr) # 解析为Period对象(表示时间间隔) parse_time_obj <- function(time_str) { hours <- as.integer(str_extract(time_str, "\\d+(?=H)")) mins <- as.integer(str_extract(time_str, "\\d+(?=M)")) secs <- as.integer(str_extract(time_str, "\\d+(?=S)")) hours(hours) + minutes(mins) + seconds(secs) } # 测试 parse_time_obj("7H 30M 4S") # 输出:[1] "7H 30M 4S"
关于格式疑问:目前没有广泛使用的R包将这种格式作为时间存储的标准格式,更可能是人为自定义的显示格式,比如为了节省字符长度或适配特定场景的可读性需求。
内容的提问来源于stack exchange,提问作者julianne
相关产品推荐
相关产品推荐

