103

我有一个如下所示的数据集:

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()需要一天并且无法为一天设置标准值?哪个功能解决了我的问题?

4

7 回答 7

88

由于日期对应于数值和开始日期,因此您确实需要日期。如果你真的需要你的数据是日期格式,你可以手动将日期固定到每个月的第一天,方法是将它粘贴到日期:

month <- "2009-03"
as.Date(paste(month,"-01",sep=""))
于 2011-06-05T12:46:15.123 回答
64

试试这个。(这里我们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 轴不是很漂亮,但如果您实际上有更多数据,它可能没问题,或者您可以使用示例部分中显示的花哨 X 轴的代码?plot.zoo

上面创建的动物园系列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"

笔记:

  1. "yearmon"类对象按日历顺序排序。

  2. 这将以相等的间隔绘制每月点,这可能是想要的;但是,如果希望以与每个月的天数成比例的不等间距绘制点,则将索引转换z"Date"class: time(z) <- as.Date(time(z))

于 2011-06-05T12:58:02.803 回答
34

如果您需要日期格式为最简洁的解决方案:

library(zoo)
month <- "2000-03"
as.Date(as.yearmon(month))
[1] "2000-03-01"

as.Date将为您将每个月的第一天固定为 yearmon 对象。

于 2014-02-07T01:50:30.127 回答
27

您还可以使用 -package 中的parse_date_timeorfast_strptime函数实现此目的lubridate

> 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- 参数:

> 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")
于 2017-06-25T10:15:41.960 回答
15

使用任何时间包:

library(anytime)

anydate("2009-01")
# [1] "2009-01-01"
于 2017-03-07T21:29:03.613 回答
6

实际上,正如上面提到的(以及 SO 的其他地方),为了将字符串转换为日期,您需要一个特定的月份日期。从as.Date()手册页:

如果日期字符串未完全指定日期,则返回的答案可能是系统特定的。最常见的行为是假设缺少的年、月或日是当前的。如果它错误地指定了一个日期,可靠的实现将给出一个错误并且日期报告为 NA。不幸的是,一些常见的实现(例如glibc)是不可靠的并且猜测预期的含义。

一个简单的解决方案是将日期粘贴"01"到每个日期并使用strptime()将其指示为该月的第一天。


对于那些在 R 中寻求处理日期和时间的更多背景知识的人:

在 R 中,时间使用POSIXctPOSIXlt类和日期使用Date类。

日期存储为自 1970 年 1 月 1 日以来的天数,时间存储为自 1970 年 1 月 1 日以来的秒数。

因此,例如:

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"
于 2015-12-17T16:28:07.687 回答
1

我认为@ben-rollert 的解决方案是一个很好的解决方案。

如果要在新包内的函数中使用此解决方案,则必须小心。

开发包时,建议使用语法packagename::function_name()(参见http://kbroman.org/pkg_primer/pages/depends.html)。

在这种情况下,您必须使用库as.Date()定义的版本。zoo

这是一个例子:

> 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"))
于 2016-11-09T13:31:07.090 回答