Extract month and year from a zoo::yearmon object

我有一个 yearmon物体:

require(zoo)
date1 <- as.yearmon("Mar 2012", "%b %Y")
class(date1)
# [1] "yearmon"

我如何从中提取月份和年份?

month1 <- fn(date1)
year1 <- fn(date1)

我应该使用什么功能来代替 fn()

173528 次浏览

You can use format:

library(zoo)
x <- as.yearmon(Sys.time())
format(x,"%b")
[1] "Mar"
format(x,"%Y")
[1] "2012"

对类 "yearmon"的对象使用 format()方法

date1 <- as.yearmon("Mar 2012", "%b %Y")

然后我们可以根据需要提取日期部分:

> format(date1, "%b") ## Month, char, abbreviated
[1] "Mar"
> format(date1, "%Y") ## Year with century
[1] "2012"
> format(date1, "%m") ## numeric month
[1] "03"

它们以字符的形式返回。如果您希望将年份或数字月份作为数字变量,请在适当的地方包装 as.numeric(),例如。

> as.numeric(format(date1, "%m"))
[1] 3
> as.numeric(format(date1, "%Y"))
[1] 2012

有关详细信息,请参阅 ?yearmon?strftime-后者解释了您可以使用的占位符。

润滑油包装在这方面的表现令人惊叹:

> require(lubridate)
> month(date1)
[1] 3
> year(date1)
[1] 2012

我知道 OP 在这里使用的是 zoo,但是我发现这个线程正在为同样的问题搜索一个标准的 ts解决方案。所以我想我也应该为 ts增加一个无 zoo的答案。

# create an example Date
date_1 <- as.Date("1990-01-01")
# extract year
as.numeric(format(date_1, "%Y"))
# extract month
as.numeric(format(date_1, "%m"))

对于大型矢量:

y = as.POSIXlt(date1)$year + 1900    # x$year : years since 1900
m = as.POSIXlt(date1)$mon + 1        # x$mon : 0–11

根据注释,结果应该是月号(1月 = 1)和4位数的年份,所以假设我们刚刚运行了问题中的代码,我们有以下内容。除了已经在问题中使用的软件包之外,这个软件包非常短,而且比其他任何解决方案都快得多(参见下面的基准测试部分)。

cycle(date1)
## [1] 3
as.integer(date1)
## [1] 2012

基准

对于一个长度为1000的年度对象,上面的解决方案比其他任何一个年度对象的速度都快1000倍,比月度对象的速度快200倍。

library(zoo)
library(microbenchmark)
library(lubridate)


ym <- as.yearmon(rep(2000, 1000))


microbenchmark(
as.integer(ym),
as.numeric(format(ym, "%y")),
as.POSIXlt(ym)$year + 1900,
year(ym)
)


Unit: microseconds
expr     min       lq     mean   median       uq     max neval cld
as.integer(ym)    18.2    27.90    28.93    29.15    31.15    51.2   100 a
as.numeric(format(ym, "%y")) 46515.8 47090.05 48122.28 47525.00 48080.25 69967.6   100   c
as.POSIXlt(ym)$year + 1900 40874.4 41223.65 41798.60 41747.30 42171.25 44381.2   100  b
year(ym) 40793.2 41167.70 42003.07 41742.40 42140.30 65203.3   100  b
 

microbenchmark(
cycle(ym),
as.numeric(format(ym, "%m")),
as.POSIXlt(ym)$mon + 1,
month(ym)
)


Unit: microseconds
expr     min      lq      mean   median       uq     max neval cld
cycle(ym)   138.1   166.0   173.893   172.95   181.45   344.0   100 a
as.numeric(format(ym, "%m")) 46637.1 46954.8 47632.307 47325.90 47672.40 67690.1   100   c
as.POSIXlt(ym)$mon + 1 40923.3 41339.1 41976.836 41689.95 42078.15 65786.4   100  b
month(ym) 41056.4 41408.9 42082.975 41743.35 42164.95 66651.0   100  b

从1800年到现在,我也遇到过类似的数据问题,因此这个方法对我很有效:

data2$date=as.character(data2$date)
lct <- Sys.getlocale("LC_TIME");
Sys.setlocale("LC_TIME","C")
data2$date<- as.Date(data2$date, format = "%Y %m %d") # and it works