我正在使用从Teradata导出的.csv数据。有几列原本是带时区的时间戳,所以在加载R中的.csv之后,我想将这些列(作为字符串加载)转换为POSIXlt或POSIXct。我使用的是strptime
,但.csv文件中的时区格式与strptime
所期望的格式不匹配。例如,它期望-0400
但.csv的格式为-04:00
,其中冒号分隔小时和分钟。
我可以移除结肠,但这是一个额外的步骤和复杂性我想尽可能避免。有没有办法告诉strptime
使用不同的时区格式(%z
)?
以下是一个例子:
## Example data:
x <- c("2011-10-12 22:17:13.860746-04:00", "2011-10-12 22:17:13.860746+00:00")
format <- "%Y-%m-%d %H:%M:%OS%z"
## Doesn't work:
strptime(x,format)
## [1] NA NA
## Ignores the timezone:
as.POSIXct(x)
## [1] "2011-10-12 22:17:13 EDT" "2011-10-12 22:17:13 EDT"
## Remove the last colon:
x2 <- gsub("(.*):", "\\1", x)
x2
## [1] "2011-10-12 22:17:13.860746-0400" "2011-10-12 22:17:13.860746+0000"
## This works, but requires extra processing (removing the colon)
strptime(x2,format)
## [1] "2011-10-12 22:17:13" "2011-10-12 18:17:13"
所以我希望使用类似strptime(x,"%Y-%m-%d %H:%M:%OS%zz")
的内容来实现最后的结果,其中%zz
是识别-04:00
格式的时区的自定义表达式。或者%zH:%zM
可能会更好。
如果无法做到这一点,是否有人有灵活/灵活的功能将字符串(各种格式)转换为data.frame / data.table的多列日期?
答案 0 :(得分:6)
事实证明lubridate
可以处理这种格式:
library(lubridate)
ymd_hms(x)
## [1] "2011-10-13 02:17:13 UTC" "2011-10-12 22:17:13 UTC"
或者,要在本地时区显示:
with_tz(ymd_hms(x))
## [1] "2011-10-12 22:17:13 EDT" "2011-10-12 18:17:13 EDT"
为了更灵活(仍使用lubridate
):
parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z")
为了加快速度(在lubridate
选项中):
lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO")
时序:
microbenchmark(
ymd_hms(x),
parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z"),
lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO"),
strptime(gsub("(.*):", "\\1", x), format)
)
## Unit: microseconds
## expr min lq mean median uq max neval
## ymd_hms(x) 1523.819 1578.495 1715.14577 1629.5385 1744.3695 2850.393 100
## parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z") 1108.676 1150.633 1273.77301 1190.3315 1264.8050 5947.204 100
## lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO") 89.838 103.390 112.45338 107.8425 115.2265 216.512 100
## strptime(gsub("(.*):", "\\\\1", x), format) 46.716 58.294 71.90934 69.9415 86.5860 105.044 100
答案 1 :(得分:2)
我刚刚遇到这个问题试图达到同样的目的。
我发现修复它的唯一方法就是使用正则表达式来移除冒号,正如您所提到的那样。您可以稍微收紧正则表达式,以避免在替换中出错。
x2 <- gsub('^([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]+[+-][0-9]{2}):([0-9]{2})$',
'\\1\\2',
x)
# [1] "2011-10-12 22:17:13.860746-0400" "2011-10-12 22:17:13.860746+0000"