将 R 翻译成 Rcpp:向量中连续日期之间的平均时差

Translating R to Rcpp: mean time difference between successive dates in vector

我有一个 R 函数,它接受一个排序日期向量(降序),returns 向量中连续日期之间的平均时差。我正在尝试将此 R 函数转换为 Rcpp 函数。

这是我目前的情况:

sorted_dates <- as.Date(c("2015-09-25", "2015-06-12",
                        "2015-06-12", "2015-03-26"))

mean_time_difference <- function(sorted_dates){
### Takes a vector of dates sorted in descending order
### Returns the mean time difference between dates.

time_differences <- integer()
for(i in 1:(length(sorted_dates) - 1)){
time_differences[i] <- as.integer( sorted_dates[i] - sorted_dates[i+1])
}

return(mean(time_differences))

}

这是我目前对 Rcpp 的错误翻译:

cppFunction('double mean_time_diff(DateVector sorted_dates) {
/* Takes a vector of dates sorted in descending order
*/ Returns the mean time difference between dates. 

int n = sorted_dates.size();
IntegerVector time_diff;

for(int i=1; i < (n-1); i++){
  time_diff.push_back( sorted_dates[i] - sorted_dates[i+1] );
}

int m = time_diff.size();
double total = 0; 
for(int i=1; i < m; i++) {
  total += time_diff[i];
}

return total / m;

}')

mean_time_difference(sorted_dates)
mean_time_diff(sorted_dates)

我确信 R 和 Rcpp 函数都有很多可以改进的地方。谁能告诉我如何在 Rcpp 中最好地实现该功能?

这就是您要寻找的,采用简单的 R 方法:

> sorted_dates <- as.Date(c("2015-09-25", "2015-06-12", 
+                         "2015-06-12", "2015-03-26"))
> mean(diff(sorted_dates))
Time difference of -61 days
> mean(as.numeric(diff(sorted_dates)))
[1] -61
> 

可以用 Rcpp 做这些事情,但你可能在基础 R 中做它们,或者用任何附加聚合实用程序——我喜欢 data.table.

为了完整起见,根据@DirkEddelbuettel 的提示,这里是使用 Rcpp 的解决方案:

cppFunction('double mean_time_diff(DateVector sorted_dates) {

  int n = sorted_dates.size();
  IntegerVector time_diff;

  for(int i=0; i < (n-1); i++){
    time_diff.push_back( sorted_dates[i] - sorted_dates[i+1] );
  }

  int m = time_diff.size();
  double total = 0; 

  for(int i=0; i < m; i++) {
    total += time_diff[i];
  }

  return total / m;

}')

关键是要记住 C++ 是零索引的。

几点注意事项:

  1. C++ 索引从 0 而不是 1 开始!
  2. 使用 [] 提供边界检查(导致未定义的行为),其中 () 为访问数组提供边界检查。
  3. 避免使用 .push_back,因为它会复制数据,因为代理模型会导致很多心痛(更何况是减速)。
  4. 此外,您可能应该将此函数拆分为一个时间差例程 (see a differencing generic for armadillo),然后是一个均值函数。

现在,是时候编写一些代码了:

// [[Rcpp::export]]
Rcpp::IntegerVector diff_date(Rcpp::DateVector sorted_dates){
  // Length of Time Series
  unsigned int n = sorted_dates.size();

  // Initialize result   
  Rcpp::IntegerVector time_diff(n-1);

  // Difference operator X_t - X_{t+1}
  for(unsigned int i = 0; i < (n-1); i++){
    time_diff[i] = sorted_dates[i] - sorted_dates[i+1];
  }

  // Return differenced series:
  return time_diff;
}

// [[Rcpp::export]]
double mean_diff_date(Rcpp::DateVector sorted_dates){

  // Difference time series by above routine
  Rcpp::IntegerVector time_diff = diff_date(sorted_dates);

  // Length of Time Series
  unsigned int n = time_diff.size();

  // Mean routine (could be replaced with mean() )
  double total = 0;

  for(unsigned int i = 0; i < n; i++){
     total += time_diff[i];
  }

  return total/n;
}

编辑:我刚刚注意到@Frank 已经在评论中提出了这个建议。我仍然认为代码有用,所以我会把它留在这里。

除此之外,您的问题实际上比看起来更简单,并且由于您(我假设)正在寻找处理速度快的解决方案,因此简化问题可能会更好,而不是尝试将其重新编码为另一种语言。特别是因为您不需要进行任何排序,只需保留您的日期设置,然后应用以下内容。

您要求的是排序后一组数字之间的平均差,这与:

as.numeric( ( max( dates ) - min( dates ) ) / ( length( dates ) - 1L ) )

这是系列的总范围除以 "gaps" 的数量(等于值的数量减去 1)。

我没有测试过,但我相信上面的方法会比这里的其他方法快得多,尤其是对于大型数据集。