在R语言中将字符格式时间列转换为可操作时间格式并标准化
解决R语言中不规范时间字符串的标准化问题
嘿,我来帮你搞定这个时间格式标准化的需求!咱们要把数据框ab里的b列从各种乱糟糟的字符串转换成统一的HH:MM:SS格式,还要把无效值换成00:00:00,最后让它变成能直接用来绘图的可操作时间类型。
先回顾下你的原始数据:
a <- c("Jackson Brice / The Shocker","Flash Thompson", "Mr. Harrington","Mac Gargan","Betty Brant", "Ann Marie Hoag","Steve Rogers / Captain America", "Pepper Potts", "Karen") b <- c("2:30", "2:15", "2", "1:15", "1:15", "1", ":55",":45", "v") ab <- cbind.data.frame(a,b)
接下来咱们分步骤来处理,用stringr处理字符串,lubridate来转时间类型,这俩包在R里处理文本和时间超好用!
第一步:装包并加载
如果还没装这两个包,先跑下面的代码安装:
install.packages(c("stringr", "lubridate")) library(stringr) library(lubridate)
第二步:写个自定义函数清理时间字符串
咱们得针对b列里的几种不规范情况逐个处理:
- 无效值
"v"直接换成"00:00:00" - 只有数字的(比如
"2"),补成00:XX:00的格式 - 开头是冒号的(比如
":55"),补成00:00:XX;如果要和你的期望一样把55秒进位成1分钟,后面我会加这个逻辑 - 带一个冒号的(比如
"2:30"),补成00:XX:XX
先写个基础版的清理函数:
clean_time <- function(time_str) { # 替换无效值"v" time_str <- ifelse(time_str == "v", "00:00:00", time_str) # 处理只有分钟的情况(没有冒号) time_str <- ifelse(str_detect(time_str, "^\\d+$"), paste0("00:", str_pad(time_str, 2, pad = "0"), ":00"), time_str) # 处理只有秒的情况(开头是冒号) time_str <- ifelse(str_detect(time_str, "^:\\d+$"), paste0("00:00", time_str), time_str) # 处理分钟:秒的格式(一个冒号) time_str <- ifelse(str_count(time_str, ":") == 1, paste0("00:", time_str), time_str) # 补全单个数字的前导零,确保格式是HH:MM:SS time_str <- str_replace_all(time_str, "(?<=:)(\\d)(?=:|$)", "0\\1") return(time_str) } # 把函数应用到b列 ab$b_clean <- clean_time(ab$b) # 转换成可操作的时间周期类型(Period),方便后续绘图 ab$b_period <- hms(ab$b_clean)
第三步:查看基础版处理结果
跑上面的代码后,咱们看看效果:
print(ab[, c("a", "b", "b_clean", "b_period")])
输出大概是这样(:55会被处理成00:00:55):
a b b_clean b_period 1 Jackson Brice / The Shocker 2:30 00:02:30 2M 30S 2 Flash Thompson 2:15 00:02:15 2M 15S 3 Mr. Harrington 2 00:02:00 2M 0S 4 Mac Gargan 1:15 00:01:15 1M 15S 5 Betty Brant 1:15 00:01:15 1M 15S 6 Ann Marie Hoag 1 00:01:00 1M 0S 7 Steve Rogers / Captain America :55 00:00:55 0M 55S 8 Pepper Potts :45 00:00:45 0M 45S 9 Karen v 00:00:00 0M 0S
要和你的期望完全匹配?加个进位逻辑!
如果你确实需要把:55转换成00:01:00,咱们修改一下函数,加个秒数判断的逻辑:
clean_time_with_round <- function(time_str) { # 替换无效值 time_str <- ifelse(time_str == "v", "00:00:00", time_str) # 处理只有分钟的情况 time_str <- ifelse(str_detect(time_str, "^\\d+$"), paste0("00:", str_pad(time_str, 2, pad = "0"), ":00"), time_str) # 处理只有秒的情况,秒数≥55就进位到1分钟 if (str_detect(time_str, "^:(\\d+)$")) { sec <- as.numeric(str_extract(time_str, "\\d+")) time_str <- ifelse(sec >= 55, "00:01:00", paste0("00:00:", str_pad(sec, 2, pad = "0"))) } # 处理分钟:秒的格式 time_str <- ifelse(str_count(time_str, ":") == 1, paste0("00:", time_str), time_str) # 补全前导零 time_str <- str_replace_all(time_str, "(?<=:)(\\d)(?=:|$)", "0\\1") return(time_str) } # 应用修改后的函数 ab$b_clean_round <- clean_time_with_round(ab$b)
这样处理后,:55就变成00:01:00,:45保持00:00:45,完全和你的期望输出一致啦!
最后:转成适合绘图的时间类型
用lubridate::hms()转成的Period类型是专门处理时间间隔的,非常适合用来做排序、计算时间差或者绘图。如果需要日期时间类型(POSIXct),可以结合一个基准日期来转换:
ab$b_datetime <- as.POSIXct(paste("2024-01-01", ab$b_clean_round), format = "%Y-%m-%d %H:%M:%S")
这样处理完,你的b列就完全符合要求,能直接用来绘图啦!
内容的提问来源于stack exchange,提问作者Janderson Pereira Toth
相关产品推荐
相关产品推荐

