Data Frame无法正确解析时分秒格式问题求助
解决CSV日期时间解析时时间自动附加日期的问题
问题场景
你尝试读取包含独立日期、时间列的CSV文件为R Data Frame,但遇到了一个小麻烦:自定义解析时间列后,结果里的时间自动带上了日期,不是你想要的纯时间格式。
先回顾下你的情况:
- 原始CSV数据(注意看起来所有记录是用空格分隔的,每行没有换行):
10/05/18,0:00:03,SP-PALL-01,0.05 10/05/18,0:00:03,SP-PDALL-05,0.1 10/05/18,0:00:03,PT33-PT34,0.21249676 10/05/18,0:00:03,PT32-PT36,0.42838383 10/05/18,0:00:03,SP-PDAH-03,0.6 10/05/18,0:00:03,PT32-PT34,0.60584164 10/05/18,0:00:03,SP-PDAH-04,0.7 10/05/18,0:00:03,PT-31,2.4700246 10/05/18,0:00:03,PT32-PT31,12.394566 10/05/18,0:00:03,PT-32,14.782079
- 你尝试的自定义类解析代码:
setClass('tagDate') setClass('tagTime') setAs("character","tagDate", function(from) as.Date(from, format="%d/%m/%y")) setAs("character","tagTime", function(from) as.POSIXct(from, format="%H:%M:%S")) df <- read.csv('allTags-cleanup-copy.csv',header = FALSE, colClasses=c('tagDate','tagTime','character','real')) names(df) <- c('tagDate', 'tagTime', 'tagName', 'tagValue') head(df)
- 得到的结果里
tagTime列变成了2018-05-10 00:00:03,自动附加了日期,不是你想要的纯时间。
问题根源
POSIXct类型在R里是带日期的时间戳,当你只传入时间字符串时,它会自动用当前系统日期(这里刚好和你的日期列一致,纯属巧合)填充缺失的日期部分,所以显示时会带上日期。如果只想存储纯时间,需要用专门的纯时间类型,而不是POSIXct。
两种可行解决方案
方案1:用hms包存储纯时间
hms包专门为小时-分钟-秒格式的时间设计,不会附加日期,操作简单:
- 先安装并加载包:
install.packages("hms") library(hms)
- 读取并解析数据:
# 先按字符列读取,避免自动解析问题 df <- read.csv('allTags-cleanup-copy.csv', header = FALSE, colClasses = c('character','character','character','numeric')) names(df) <- c('tagDate', 'tagTime', 'tagName', 'tagValue') # 解析日期列 df$tagDate <- as.Date(df$tagDate, format = "%d/%m/%y") # 解析时间列为hms类型(纯时间) df$tagTime <- parse_hms(df$tagTime) # 查看结果 head(df)
这样tagTime列就会显示为00:00:03,完全不带日期。
方案2:用lubridate包的Period类型
lubridate是R处理日期时间的热门工具包,它的hms()函数可以把时间字符串转为纯时间的Period对象:
- 安装加载包:
install.packages("lubridate") library(lubridate)
- 处理数据:
df <- read.csv('allTags-cleanup-copy.csv', header = FALSE, colClasses = c('character','character','character','numeric')) names(df) <- c('tagDate', 'tagTime', 'tagName', 'tagValue') # dmy()自动识别日/月/年格式的日期 df$tagDate <- dmy(df$tagDate) # hms()转为纯时间 df$tagTime <- hms(df$tagTime) head(df)
补充:如果需要POSIXct但只想显示纯时间
如果后续分析必须用POSIXct类型,只是不想显示日期,可以修改打印格式:
# 保留秒的小数部分(如果需要) options(digits.secs = 3) # 设置tagTime列的显示格式 print(df, format = list(tagTime = "%H:%M:%OS"))
注意:底层存储还是带日期的,只是显示时隐藏了。
额外提醒:原始CSV的行分隔问题
看你的原始数据,所有记录是用空格分隔的,没有换行?如果是这样,read.csv可能无法正确识别每条记录,需要先预处理:
# 读取原始文本内容 raw_text <- readLines('allTags-cleanup-copy.csv') # 按空格分割成单独的记录 records <- strsplit(raw_text, " ")[[1]] # 用分割后的记录创建Data Frame temp_df <- read.csv(text = records, header = FALSE) # 再进行后续的日期时间解析
内容的提问来源于stack exchange,提问作者cogitoergosum
相关产品推荐
相关产品推荐

