【问题标题】:R: efficient ways to add months to dates?R:将月份添加到日期的有效方法?
【发布时间】:2015-04-01 00:40:23
【问题描述】:

我有一个数百万行的 data.table,其中一列是日期列。我想为该列中的所有日期添加 12 个月并创建一个新列。所以我使用 dplyr 和 lubridate 包,例如

library(dplyr)
library(lubridate)
new_data <- data %>% mutate(date12m = date %m+% months(12))

这很有效,但是对于大型数据集来说非常慢。我错过了什么吗?如何加快速度?对于这么简单的任务,我一般不希望 R 运行超过 10 分钟

编辑:

我注意到我的解决方案已经比使用 as.yearmon 更有效。感谢 Beauvel 上校的解决方案

a <- data.frame(date = rep(today(),1000000))


func = function(u) {
  d = as.Date(as.yearmon(u)+1, frac=1) 
  if(day(u)>day(d)) return(d)
  day(d) = day(u)
  d
} 

pt <- proc.time()
a <- a %>% mutate(date12m = func(date))
data.table::timetaken(pt)


pt <- proc.time()
a <- a %>% mutate(date12m = date %m+% 12)
data.table::timetaken(pt)

【问题讨论】:

  • 您能提供一小部分数据吗?
  • 希望答案有所帮助,您需要在应用我的函数之前将所需的列转换为日期。
  • 我同意这应该更快,但考虑到日期以 1970 年 1 月 1 日以来的秒数存储,这并不是一项简单的任务

标签: r dplyr lubridate


【解决方案1】:

我也在使用 R 中的大数据帧,你可以使用包 DescTools,它有一个名为 AddMonths(date,NoOfMonths) 的函数。

对我来说效果很好。

> a <- ymd("2011-09-9")
> b <- AddMonths(a,1)
> b

[1] "2011-10-09"

【讨论】:

  • 适用于数据帧。 seq 不适用于数据帧。您需要进行一些调整才能在数据帧上使用它。 AddMonths 非常简单。
  • 如何应用到数据框。这似乎很慢!
【解决方案2】:

只需用month加1:

x=seq.Date(from=as.Date("2007-01-01"), to=as.Date("2014-12-12"), by="day")
month(x) = month(x) + 1

#> head(x)
#[1] "2007-02-01" "2007-02-02" "2007-02-03" "2007-02-04" "2007-02-05" "2007-02-06"

编辑:根据@akrun 评论,这里是解决方案,使用来自zoo 包的as.yearmon。诀窍是在取下个月最后一天的日期时快速检查:

library(zoo)

func = function(u)
{
    d = as.Date(as.yearmon(u)+1/12, frac=1) 
    if(day(u)>day(d)) return(d)
    day(d) = day(u)
    d
} 

x=as.Date(c("2014-01-31","2015-02-28","2013-03-02"))
#> as.Date(sapply(x, func))
#[1] "2014-02-28" "2015-03-28" "2013-04-02"

【讨论】:

  • 谢谢,但如果您显示一些基准会更好,因为 OP 需要高效的代码。从我的基准测试来看,与mondate 相比,OP 的解决方案是有效的。虽然没有检查你的:-)
  • 我在应用到测试数据集时收到警告消息。 In if (day(u) &gt; day(d)) return(d) : the condition has length &gt; 1 and only the first element will be used
  • 你的数据集是什么?我根本没有这个消息。这意味着 day(u) 是一个不应该是这种情况的向量。
  • 我的理解是您的代码可以应用为data %&gt;% mutate(date12m = func(date)) 但是根据您的示例,它是否再次被sapply 循环?
  • 数据集是set.seed(24); data &lt;- data.frame(date=seq(as.Date('2011-01-01'), length.out=20, by='1 month'), val=rnorm(20))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多