R语言CSV读写datetime时区丢失、时长单位及格式转换问题求解
注:示例代码中构造
tibble的代码缺少右闭合括号,运行前请自行补上。
核心前提说明:CSV是纯文本格式,仅能存储字符串/数值,无法存储R对象的属性(时区、单位、类信息等),你遇到的大多问题均是该特性导致,解决方案分两类:要么读写CSV时手动还原属性,要么改用支持属性存储的二进制格式(比如R原生rds)。
问题1:datetime时区丢失修复
两种方案可选:
- 坚持用CSV的话,读入时手动指定时区即可:
如果不想硬编码时区,可以在写入CSV前新增一列存储时区信息,读入时用该列动态指定即可。tbl_in <- read_csv("sample.csv", col_types = cols()) %>% mutate( start_trip = ymd_hms(start_trip, tz = "America/New_York"), end_trip = ymd_hms(end_trip, tz = "America/New_York") ) - 更省事的方案是改用R原生rds格式存储,所有属性完整保留:
# 写入 saveRDS(tbl_out, "sample.rds") # 读取 tbl_in <- readRDS("sample.rds")
问题2:给duration添加mins单位(不转字符)
直接将数值转为difftime或者units类型即可,底层还是数值,完全支持运算,打印时自带单位:
library(units) tbl_out <- tbl_out %>% mutate(duration = set_units(duration, "mins"))
打印时会自动显示X mins,做加减乘除运算和普通数值没有区别。
问题3:HH:MM格式且支持基础运算
用hms包的hms类即可,该类是专门为时间差设计的,默认打印为HH:MM:SS格式,完全支持算术运算、和datetime类运算:
library(hms) tbl_out <- tbl_out %>% mutate( duration_hms = hms(minutes = duration), time_diff_hms = hms(minutes = time_diff) ) # 测试加法 tbl_out$start_trip + tbl_out$duration_hms # 结果和end_trip完全一致
问题4:74.5分钟展示为74:30格式
可以自定义格式化方法,同时保留底层数值的运算能力:
# 自定义格式化函数 format_mins <- function(x) { whole_mins <- floor(x) secs <- round((x - whole_mins) * 60) sprintf("%d:%02d", whole_mins, secs) } # 测试 format_mins(74.5) # 输出 "74:30"
如果要让列默认打印为该格式,同时保留运算能力,可以给列添加自定义print方法,或者直接在需要展示的时候调用该函数即可,不会影响底层数值的运算。
问题5:回读CSV后time_diff丢失分钟单位
和问题1的逻辑一致,两种方案:
- CSV读入后手动转回带单位的类型:
tbl_in <- tbl_in %>% mutate(time_diff = as.difftime(time_diff, units = "mins")) - 改用rds格式存储,读入后所有单位属性自动保留,无需额外处理。
内容的提问来源于stack exchange,提问作者SiH
相关产品推荐
相关产品推荐

