strptime、as.POSIXct和as.Date返回意外的NA

18

当我尝试解析以下格式的时间戳:"Thu Nov 8 15:41:45 2012"时,只返回 NA

我使用的是 Mac OS X、R 2.15.2 和 Rstudio 0.97.237。我的操作系统语言为荷兰语,我认为这可能与此有关。

当我尝试使用 strptime 时,也会返回 NA

var <- "Thu Nov 8 15:41:45 2012"
strptime(var, "%a %b %d %H:%M:%S %Y")
# [1] NA

as.POSIXct也无法正常工作:

as.POSIXct(var, "%a %b %d %H:%M:%S %Y")
# [1] NA

我也尝试了对上面的字符串使用as.Date,但没有包含%H:%M:%S组件:

as.Date("Thu Nov 8 2012", "%a %b %d %Y")
# [1] NA

有什么想法,我可能做错了什么?


1
我在Ubuntu和R基础上无法重现您的错误。对我来说,strptime创建了一个POSIXlt而不是POSIXct时间对象。最后,请尝试使用as.POSIXct(var, format=...),看看是否更顺利。 - Justin
2个回答

26
我认为正如你猜测的那样,strptime 无法解析你的日期时间字符串,是因为你的地区设置导致的。你的字符串包含了缩写的星期几(%a)和缩写的月份(%b)。这些时间规范在?strptime中有描述:

细节

%a: 当前系统环境下缩写的星期几名称

%b: 当前系统环境下缩写的月份名称。

"请注意,缩写名称是特定于平台的(虽然标准规定在C地区,它们必须是大写英文名称的前三个字母:"

"如果要在输入格式中使用%a%b%h,则了解缩写名称是必不可少的:请参阅示例以查看如何检查。"

另请参阅

[...] locales 来查询或设置地区信息。

locales 的问题也适用于 as.POSIXctas.POSIXltas.Date

?as.POSIXct中有:

细节

如果指定了format,请记住,一些格式规范是特定于地区的,你可能需要通过Sys.setlocale适当设置LC_TIME类别。这通常会影响到%b%B (月份名称) 和 %p (上午/下午) 的使用。

?as.Date中有:

细节

在适当和可用的情况下,使用与字符字符串转换相关的特定于地区的转换。这会影响天数和月份的名称。


因此,如果字符串中的星期几和月份名称与当前地区不同,strptimeas.POSIXctas.Date将无法正确解析该字符串,并返回NA
然而,你可以通过更改locales来解决此问题:
# First save your current locale
loc <- Sys.getlocale("LC_TIME")

# Set correct locale for the strings to be parsed
# (in this particular case: English)
# so that weekdays (e.g "Thu") and abbreviated month (e.g "Nov") are recognized
Sys.setlocale("LC_TIME", "en_GB.UTF-8")
# or
Sys.setlocale("LC_TIME", "C") 

#Then proceed as you intended
x <- "Thu Nov 8 15:41:45 2012" 
strptime(x, "%a %b %d %H:%M:%S %Y")
# [1] "2012-11-08 15:41:45"

# Then set back to your old locale
Sys.setlocale("LC_TIME", loc) 

使用我的本地环境,我可以重现您的错误:

Sys.setlocale("LC_TIME", loc)
# [1] "fr_FR.UTF-8"

strptime(var,"%a %b %d %H:%M:%S %Y")
# [1] NA

4

我曾经遇到类似的问题,发现这个解决方案更加简洁,因为不需要手动更改任何系统设置,lubridate 包中有一个包装函数可以完成此操作,你只需设置参数 locale

date <- c("23. juni 2014", "1. november 2014", "8. marts 2014", "16. juni 2014", "12. december 2014", "13. august 2014")
df$date <- dmy(df$Date, locale = "Danish")
[1] "2014-06-23" "2014-11-01" "2014-03-08" "2014-06-16" "2014-12-12" "2014-08-13"

3
关于“无需更改任何系统设置”的说法,请注意,lubridate函数中的locale参数只是上述答案中概述的步骤的方便包装:(1)保存当前区域设置,(2)更改区域设置,(3)恢复原始区域设置。请在此处检查代码:orig_locale <- Sys.getlocale("LC_TIME"); Sys.setlocale("LC_TIME", locale); on.exit(Sys.setlocale("LC_TIME", orig_locale)) - Henrik
或者 locale = "da_DK" - Eric Fail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接