从 zoo::yearmon 对象中提取月份和年份
Posted
技术标签:
【中文标题】从 zoo::yearmon 对象中提取月份和年份【英文标题】:Extract month and year from a zoo::yearmon object 【发布时间】:2012-04-02 17:22:38 【问题描述】:我有一个yearmon
对象:
require(zoo)
date1 <- as.yearmon("Mar 2012", "%b %Y")
class(date1)
# [1] "yearmon"
如何从中提取月份和年份?
month1 <- fn(date1)
year1 <- fn(date1)
我应该用什么函数代替fn()
【问题讨论】:
【参考方案1】:基于 cmets,结果应该是月份数(一月 = 1)和 4 位数的年份,因此假设我们刚刚运行了问题中的代码,我们有以下内容。除了问题中已经使用的之外,它不使用任何额外的包,非常短并且比任何其他解决方案都快得多(请参阅下面的基准部分)。
cycle(date1)
## [1] 3
as.integer(date1)
## [1] 2012
基准测试
在长度为 1000 的 yearmon 对象上,上述解决方案的速度比其他任何一年快 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
【讨论】:
【参考方案2】:从 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
【讨论】:
【参考方案3】:对于大向量:
y = as.POSIXlt(date1)$year + 1900 # x$year : years since 1900
m = as.POSIXlt(date1)$mon + 1 # x$mon : 0–11
【讨论】:
这是最好的答案,因为 R 已经提供了方便的POSIXlt
对象,这使得 zoo 包变得不必要
@Marco,这不是真的。它正在使用来自动物园的 as.POSIXlt.yearmon。【参考方案4】:
我知道 OP 在这里使用 zoo
,但我发现这个线程在谷歌上搜索了相同问题的标准 ts
解决方案。所以我想我也会为ts
添加一个zoo
-free 答案。
# 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"))
【讨论】:
如果与问题的输入一起使用,他使用来自动物园的 format.yearmon,因此它仅使用基本 R 是不正确的。 感谢您的澄清。看起来 S3 欺骗了我。【参考方案5】:lubridate package 非常适合这种事情:
> require(lubridate)
> month(date1)
[1] 3
> year(date1)
[1] 2012
【讨论】:
谢谢你的回答。当您想要执行 if(year(date1) > 2014)year(date1) 之类的操作时,它尤其胜过其他解决方案 这绝对是我从 4000 份合同的开始日期中取出年份的要求的最佳答案。 @Ari B. Friedman 我目前正在使用 R 3.1.0 虽然这不支持lubridate
包并尝试安装它并使用 year(date) 但它给出的是日期而不是年份仅适用于格式为“2015-05-06”的日期?
@KRU 新版本的 R 有时需要几周的时间才能让存储库更新所有包。它应该适用于所有日期格式,只要它是真正的日期格式,而不是字符向量。如果仍然不能解决您的问题,并且您无法在 SO 中搜索问题的任何一个组成部分,请发布一个新的 q。【参考方案6】:
对"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
- 后者解释了您可以使用的占位符。
【讨论】:
%B 表示整月,即三月“而不是”“三月” 如果有一个包含 n 个元素的vector
,我会怎么做,比如说在一个 vector
中有 1k 个日期?
@Chrissl 和 R 一样,date1
也可以是日期向量。【参考方案7】:
你可以使用format
:
library(zoo)
x <- as.yearmon(Sys.time())
format(x,"%b")
[1] "Mar"
format(x,"%Y")
[1] "2012"
【讨论】:
我怎样才能让月份成为一个数字? (例如 3 月?) @user1169210 我在回答中提到了这一点。例如,您希望将月份的as.numeric(format(x, "%m"))
作为数字。以上是关于从 zoo::yearmon 对象中提取月份和年份的主要内容,如果未能解决你的问题,请参考以下文章