【问题标题】:Date iteration with Rcpp loop使用 Rcpp 循环进行日期迭代
【发布时间】:2023-01-10 01:26:47
【问题描述】:

出于紧固目的,我试图将 R 中的简单“for 循环”转换为 Rcpp 循环。

我有一个名为“date_vector”的日期向量,它由 X 个相同的日期组成。 对于 i 的每次迭代,我将 1 分钟添加到 date_vector 值。 R 'for 循环'(见下文)工作正常,但对于我非常大的数据集(2 年 ~ 100 万行)来说它太慢了。

我读过 Rccp 可能是加速循环的解决方案。 但是,我是一个“Rcpp”菜鸟,我正在努力转换我的循环。

有人可以帮助我并向我解释解决方案吗?非常感谢你! 祝 2023 年一切顺利。

原来的 R 循环:

for(i in 2:nrow(klines)){
  
  date_vector[i] <- date_vector[i-1]+minutes(1)
  
}

我的 Rcpp 循环尝试:

cpp_update_date_vector <- cppFunction('DateVector fonction_test(DateVector zz),
  
  int n = zz.size();
  DateVector = date_vector;
  
    for (int i = 0; i < n; i++) {
    
    date_vector[i] = date_vector[i-1] + 60; 
  
  }
')

【问题讨论】:

  • 你在这里不需要循环。只需使用date_vector[1] + lubridate::minutes(seq(nrow(klines)) - 1)。这已经在 C 级别进行了矢量化,因此在 Rcpp 中重新发明轮子几乎没有任何好处。

标签: r loops rcpp


【解决方案1】:

您可能根本不需要循环就可以实现您的目标。听起来您正在尝试将相同日期时间的向量更改为相隔一分钟的序列,对吧?如果是这样,你可以这样做:

library(lubridate) 

date_vector <- rep(ymd_hms("2020-01-01 12:00:00"), 10)

date_vector + minutes(seq_along(date_vector) - 1)
 [1] "2020-01-01 12:00:00 UTC" "2020-01-01 12:01:00 UTC"
 [3] "2020-01-01 12:02:00 UTC" "2020-01-01 12:03:00 UTC"
 [5] "2020-01-01 12:04:00 UTC" "2020-01-01 12:05:00 UTC"
 [7] "2020-01-01 12:06:00 UTC" "2020-01-01 12:07:00 UTC"
 [9] "2020-01-01 12:08:00 UTC" "2020-01-01 12:09:00 UTC"

【讨论】:

  • 普通的旧 base R 等价物怎么样 seq(as.POSIXct("2020-01-01 12:00:00"), by = "1 min", length = 10)
  • 非常感谢你 !您的解决方案很短而且效果很好。我的思绪陷入了“循环”,我没有跳出框框。
  • 为了完整起见,您也不需要lubdridate。你可以在 base R 中完成所有这些。如果你需要速度 data.table擅长在这些类型的操作以及分组、汇总、转换……
【解决方案2】:

为了完整起见,以下是在 Rcpp 中编写代码的方式:

cpp_update_date_vector <- Rcpp::cppFunction('
DatetimeVector fonction_test(DatetimeVector zz) {
    for (int i = 1; i < zz.size(); i++) {
      zz[i] = zz[i-1] + 60; 
    }
  return zz;
}
')

但它并不比基本 R seq 函数快,后者可以轻松创建相隔 1 分钟的日期时间序列。下面是对 1,000,000 长度的日期时间向量的两种方法的比较:

big_vec <- rep(as.POSIXct("2023-01-01 00:00:00"), 1000000)

microbenchmark::microbenchmark(
  Rcpp = cpp_update_date_vector(big_vec),
  base_R = seq(big_vec[1], by = "1 min", length = 1000000)
)

#> Unit: milliseconds
#>   expr      min       lq     mean   median       uq       max neval cld
#>   Rcpp 3.740001 3.752651 3.834506 3.774301 3.855301  5.367702   100   a
#> base_R 2.198901 2.311300 3.339260 2.374600 2.485352 25.751801   100   a

如果说有什么不同的话,base R 要快一点,尽管它们对整个向量的处理时间都不到 4 毫秒,所以几乎没有选择的余地。显然,基本 R 选项更可取。

【讨论】:

  • 这是一个小苹果对橘子。在不交叉的情况下进行“循环对循环”和“矢量对矢量”的战斗。
猜你喜欢
  • 2019-09-10
  • 2017-12-14
  • 2010-09-11
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 2020-10-21
  • 2014-04-27
相关资源
最近更新 更多