使用lubridate的ms函数处理超59分钟时间后arrange排序失效问题
解决时间字符串(mm:ss,分钟可超59)的排序问题
我明白你遇到的问题了——用lubridate::ms()解析时间后直接排序,结果完全不符合预期对吧?这其实是因为ms()返回的是Period类对象,它内部是把分钟、秒分开存储的,排序时的逻辑并不是按总时长来比较,尤其是当分钟数超过59时,这种存储方式会导致排序混乱。
下面给你几个靠谱的解决方案,按总时长降序排序肯定没问题:
方案1:转换成总秒数(最直观稳定)
直接计算每个时间字符串对应的总秒数,用数值型排序就不会出错:
library(tidyverse) library(lubridate) test <- structure(list(time = c("00:58", "07:30", "08:07", "15:45", "19:30", "24:30")), class = c("tbl_df", "tbl", "data.frame")) test_sorted <- test %>% # 拆分分钟和秒,计算总秒数 mutate( minutes = as.numeric(str_split(time, ":", simplify = TRUE)[,1]), seconds = as.numeric(str_split(time, ":", simplify = TRUE)[,2]), total_seconds = minutes * 60 + seconds ) %>% arrange(desc(total_seconds)) %>% # 可选:保留原时间列,删掉中间计算列 select(-minutes, -seconds) print(test_sorted)
方案2:用Duration类型排序
如果想保留lubridate的时间类,可以把Period转换成Duration(Duration是按总秒数存储的,排序逻辑就是总时长):
test_sorted <- test %>% mutate(time2 = ms(time)) %>% # 转成Duration类型,再排序 arrange(desc(as.duration(time2))) print(test_sorted)
方案3:用hms包直接解析(更简洁)
hms包专门处理时分秒格式,解析后返回的是hms类,本质是数值型的秒数,排序直接生效:
library(tidyverse) library(hms) test_sorted <- test %>% mutate(time2 = parse_hms(paste0("00:", time))) %>% # 补上前缀00:变成HH:MM:SS格式适配解析 arrange(desc(time2)) print(test_sorted)
你可以试试这几种方法,应该就能解决排序混乱的问题了~
内容的提问来源于stack exchange,提问作者jakes
相关产品推荐
相关产品推荐

