我试图将一些日志文件解析为更结构化的数据集。但是,我在解析某些时间戳时遇到问题,但并非全部。奇怪的是,它们具有相同的格式,因此无法找到问题的根源。
库:
library(stringr);library(lubridate)
strptime
首先我使用 base-r ' strptime
,但我遇到了一个特殊的问题。尽管明确给出了时区,但某些字符串仍然缺失。考虑:
> strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = "")
[1] "2013-03-31 01:57:20 CET"
> strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = "")
[1] "2013-03-31 02:01:41"
注意第一个是CET,另一个是缺少它。由于我不需要时区用于我的目的,因此如果不是因为这会在格式化日期时导致问题进一步发生并不重要。例如,如果检查数据点是否丢失:
> strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = "") %>% is.na
[1] FALSE
> strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = "") %>% is.na
[1] TRUE
在我挠了头一段时间后,我放弃了并尝试了另一个图书馆。
parse_date_time
Lubridate 旨在替代 base-r 解决方案,并提供更加用户友好的界面。它是否因相同的字符串而失败?
> parse_date_time("31/Mar/2013:01:57:20", orders = "%d/%b/%Y:%H:%M:%S")
[1] "2013-03-31 01:57:20 UTC"
> parse_date_time("31/Mar/2013:01:57:20", orders = "%d/%b/%Y:%H:%M:%S") %>% is.na
[1] FALSE
> parse_date_time("31/Mar/2013:02:01:41", orders = "%d/%b/%Y:%H:%M:%S")
[1] "2013-03-31 02:01:41 UTC"
> parse_date_time("31/Mar/2013:02:01:41", orders = "%d/%b/%Y:%H:%M:%S") %>% is.na
[1] FALSE
没有错误。
但是,上面的字符串不是唯一导致问题的字符串。据我所知,这两个字符串的格式相同,但一个失败,另一个没有:
#base
#works
strptime("31/Dec/2012:06:20:10", format = "%d/%b/%Y:%H:%M:%S")
#doesn't
strptime("01/May/2013:00:01:37", format = "%d/%b/%Y:%H:%M:%S")
#lubridate
#works
parse_date_time("31/Dec/2012:06:20:10", orders = "dbYHMS")
parse_date_time("31/Dec/2012:06:20:10", orders = "d!/b/Y:H!:M!:S!")
#doesn't
parse_date_time("01/May/2013:00:01:37", orders = "dbYHMS")
parse_date_time("01/May/2013:00:01:37", orders = "d!/b/Y:H!:M!:S!")
strptime
只返回NA
,而parse_date_time
则返回:
[1] NA
Warning message:
All formats failed to parse. No formats found.
我能想到的唯一区别是,May是一个3个字母缩写的月份名称和全名。但是,告诉它使用全名(B
而不是b
)也不起作用:
> parse_date_time("01/May/2013:00:01:37", orders = "dBYHMS")
[1] NA
Warning message:
All formats failed to parse. No formats found.
> parse_date_time("01/May/2013:00:01:37", orders = "d!/B/Y:H!:M!:S!")
[1] NA
Warning message:
All formats failed to parse. No formats found.
如何正确解析上述字符串?
答案 0 :(得分:0)
你是从非常糟糕的开始(但很容易制作,我们都在那里)假设:
由于我不需要时区用于我的目的,因此如果不是因为这会在格式化日期时导致问题进一步发生并不重要。
我不同意,强烈建议根据需要设置TZ以反映夏令时。只是打印到控制台涉及格式化,而格式化又取决于设置TZ。
见证我的盒子上发生了什么(坐在中央时区):
R> strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = "")
[1] "2013-03-31 01:57:20 CDT"
R> strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = "")
[1] "2013-03-31 02:01:41 CDT"
R>
此外:
R> is.na(strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = ""))
[1] FALSE
R> is.na(strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = ""))
[1] FALSE
R>
不需要像%>%
那样的新奇事物或包装基本功能的奇特包裹。你需要掌握正确的基础知识,否则花哨的包装工作者也无法拯救你。
编辑:结束时还有其他事情发生。解析都很好。这是明确取消设置TZ的相同集:
edd@bud:~$ TZ="" r -e 'print(strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = ""))'
[1] "2013-03-31 01:57:20 UTC"
edd@bud:~$ TZ="" r -e 'print(strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = ""))'
[1] "2013-03-31 02:01:41 UTC"
edd@bud:~$ TZ="" r -e 'print(as.numeric(strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = "")))'
[1] 1364695301
edd@bud:~$ TZ="" r -e 'print(as.numeric(strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = "")))'
[1] 1364695040
edd@bud:~$
编辑2:为了完整起见,在设置TZ
时一切正常edd@bud:~$ TZ="CET" r -e 'print(strptime("31/Mar/2013:01:57:20", format = "%d/%b/%Y:%H:%M:%S", tz = ""))'
[1] "2013-03-31 01:57:20 CET"
edd@bud:~$ TZ="CET" r -e 'print(strptime("31/Mar/2013:02:01:41", format = "%d/%b/%Y:%H:%M:%S", tz = ""))'
[1] "2013-03-31 02:01:41 CEST"
edd@bud:~$
是的,这与Rscript
或R
相同,但我碰巧在命令行中使用了littler。