将年份和月份(“yyyy-mm”格式)转换为日期?
我有一个数据集,看起来像这样:将年份和月份(“yyyy-mm”格式)转换为日期?
Month count
2009-01 12
2009-02 310
2009-03 2379
2009-04 234
2009-05 14
2009-08 1
2009-09 34
2009-10 2386
我要绘制的数据(个月x值和计为y值)。由于数据中存在空白,我想将本月的信息转换为日期。我试过:
as.Date("2009-03", "%Y-%m")
但它没有奏效。怎么了?看起来as.Date()也需要一天,并且无法为当天设置标准值?哪个功能解决了我的问题?
试试这个。 (这里我们使用text=Lines
保持示例自包含,但在现实中,我们将与文件名替换它。)
Lines <- "2009-01 12
2009-02 310
2009-03 2379
2009-04 234
2009-05 14
2009-08 1
2009-09 34
2009-10 2386"
library(zoo)
z <- read.zoo(text = Lines, FUN = as.yearmon)
plot(z)
X轴是与这个数据很漂亮,但如果你在现实中的数据越多可能没问题,或者您可以使用?plot.zoo
示例部分中显示的花式X轴代码。
动物园系列,z
,即上面创建具有"yearmon"
时间指数,看起来像这样:
> z
Jan 2009 Feb 2009 Mar 2009 Apr 2009 May 2009 Aug 2009 Sep 2009 Oct 2009
12 310 2379 234 14 1 34 2386
"yearmon"
可以单独使用,也:
> as.yearmon("2000-03")
[1] "Mar 2000"
注:
"yearmon"
类对象按日历顺序排序。这将绘出等间隔的月点,这可能是想要的;然而,如果希望以不同的间隔时间间隔绘制点,则间距与每月的天数成比例,然后将
z
的索引转换为"Date"
类:time(z) <- as.Date(time(z))
。
由于日期与数值和开始日期相对应,所以确实需要一天。如果你真的需要你的数据在日期格式,你可以解决白天到每个月的第一天通过手动将其粘贴到日期:
month <- "2009-03"
as.Date(paste(month,"-01",sep=""))
,如果你需要的日期是在日期格式最简洁的解决方案:
library(zoo)
month <- "2000-03"
as.Date(as.yearmon(month))
[1] "2000-03-01"
as.Date
将每个月的第一天定为你一个yearmon对象。
事实上,正如上面已经提到的(以及SO中的其他地方),为了将字符串转换为日期,您需要特定的月份日期。从as.Date()
使用手册页面:
如果日期字符串没有完全指定日期,则返回的答案可能是系统特定的。最常见的行为是假设失去的一年,一月或一天是当前的一个。如果它错误地指定了日期,那么可靠的实现会给出错误,并且日期被报告为NA。不幸的是,一些常见的实现(如
glibc
)是不可靠的,并猜测其意图。
一个简单的解决方案是将日期"01"
粘贴到每个日期并使用strptime()
来表明它是该月的第一天。
对于那些寻求加工日期和时间多一点背景R:
在R,次使用POSIXct
和POSIXlt
类和日期使用Date
类。
日期存储为自1970年以来和时间1月1日,被存储为自1月1日的秒数的天数,1970年
因此,举例来说:
d <- as.Date("1971-01-01")
unclass(d) # one year after 1970-01-01
# [1] 365
pct <- Sys.time() # in POSIXct
unclass(pct) # number of seconds since 1970-01-01
# [1] 1450276559
plt <- as.POSIXlt(pct)
up <- unclass(plt) # up is now a list containing the components of time
names(up)
# [1] "sec" "min" "hour" "mday" "mon" "year" "wday" "yday" "isdst" "zone"
# [11] "gmtoff"
up$hour
# [1] 9
要执行
plt - as.POSIXlt(d)
# Time difference of 16420.61 days
,并处理日期,您可以使用strptime()
(从手册页借用这些例子):关于日期和时间的操作
strptime("20/2/06 11:16:16.683", "%d/%m/%y %H:%M:%OS")
# [1] "2006-02-20 11:16:16 EST"
# And in vectorized form:
dates <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960")
strptime(dates, "%d%b%Y")
# [1] "1960-01-01 EST" "1960-01-02 EST" "1960-03-31 EST" "1960-07-30 EDT"
我认为@ ben-rollert的解决方案是一个很好的解决方案。
如果您想在新软件包中的函数中使用此解决方案,您只需要小心。
开发包时,建议使用语法packagename::function_name()
(请参阅http://kbroman.org/pkg_primer/pages/depends.html)。
在这种情况下,您必须使用由zoo
库定义的as.Date()
版本。
下面是一个例子:
> devtools::session_info()
Session info ----------------------------------------------------------------------------------------------------------------------------------------------------
setting value
version R version 3.3.1 (2016-06-21)
system x86_64, linux-gnu
ui RStudio (1.0.35)
language (EN)
collate C
tz <NA>
date 2016-11-09
Packages --------------------------------------------------------------------------------------------------------------------------------------------------------
package * version date source
devtools 1.12.0 2016-06-24 CRAN (R 3.3.1)
digest 0.6.10 2016-08-02 CRAN (R 3.2.3)
memoise 1.0.0 2016-01-29 CRAN (R 3.2.3)
withr 1.0.2 2016-06-20 CRAN (R 3.2.3)
> as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
Error in as.Date.default(zoo::as.yearmon("1989-10", "%Y-%m")) :
do not know how to convert 'zoo::as.yearmon("1989-10", "%Y-%m")' to class “Date”
> zoo::as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
[1] "1989-10-01"
所以,如果你是深化发展一个包,好做法是使用:
zoo::as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
使用anytime包:
library(anytime)
anydate("2009-01")
# [1] "2009-01-01"
这有点奇怪,它选择了“01-01”,关于选择的文档中是否有任何内容?如果它总是选择每月的第一天,也许更具说明性,以显示“anydate(”2009-03“)”。 – lmo 2017-09-01 18:01:35
@lmo没有检查文档,我认为这是“常见”的做法,当dd缺少选择第一天。 – zx8754 2017-09-01 18:47:17
这很有道理。我隐约记得,然后发现是什么引发了评论。从'?strptime'的Note部分:*输入字符串不需要完全指定日期:假定未指定的秒,分钟或小时为零,并且未指定的年,月或日是当前日期。 (但是,如果指定了一个月份,则该月份的日期必须由%d或%e指定,因为该月份的当前日期不需要在指定的月份有效。)*看起来像威震天的答案包含类似来自'as.Date'的一段文档。 – lmo 2017-09-01 18:52:37
您也可以通过parse_date_time
或fast_strptime
函数来实现此目的从lubridate
-package NS:
> parse_date_time(dates1, "ym")
[1] "2009-01-01 UTC" "2009-02-01 UTC" "2009-03-01 UTC"
> fast_strptime(dates1, "%Y-%m")
[1] "2009-01-01 UTC" "2009-02-01 UTC" "2009-03-01 UTC"
这两个之间的区别在于,parse_date_time
允许lubridate风格的格式规范,而fast_strptime
需要相同的格式规范作为strptime
。
用于指定时区,你可以使用tz
-parameter:
> parse_date_time(dates1, "ym", tz = "CET")
[1] "2009-01-01 CET" "2009-02-01 CET" "2009-03-01 CET"
当你在你的日期时间数据的不规则性,可以使用truncated
-parameter指定多少违规行为被允许:
> parse_date_time(dates2, "ymdHMS", truncated = 3)
[1] "2012-06-01 12:23:00 UTC" "2012-06-01 12:00:00 UTC" "2012-06-01 00:00:00 UTC"
使用的数据
dates1 <- c("2009-01","2009-02","2009-03")
dates2 <- c("2012-06-01 12:23","2012-06-01 12",'2012-06-01")
日期还有其他什么格式?我看到了POSIX和ISO的东西,但我不确定这些是不同的格式。我认为这些只是功能,... – 2011-06-05 12:57:51
值得注意的是,你可以指定一天在格式化程序中相同,所以你可以做'as.Date(month,format ='%Y-%m-01') '并取得相同的结果。这种“感觉”比我更喜欢,因为指定每个月的同一日期更多地是日期和字符串操作的格式,但也许这是无稽之谈。 – JBecker 2013-05-24 16:57:56
@JBecker你的建议对我不起作用。 '> as.Date(“2016-01”,format =“%Y-%m-01”) #[1] NA'。 我正在使用R 3.3.1 – n8sty 2017-01-20 20:43:57