将 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++ 是零索引的。
几点注意事项:
- C++ 索引从 0 而不是 1 开始!
- 使用
[]
不 提供边界检查(导致未定义的行为),其中 ()
为访问数组提供边界检查。
- 避免使用
.push_back
,因为它会复制数据,因为代理模型会导致很多心痛(更何况是减速)。
- 此外,您可能应该将此函数拆分为一个时间差例程 (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)。
我没有测试过,但我相信上面的方法会比这里的其他方法快得多,尤其是对于大型数据集。
我有一个 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++ 是零索引的。
几点注意事项:
- C++ 索引从 0 而不是 1 开始!
- 使用
[]
不 提供边界检查(导致未定义的行为),其中()
为访问数组提供边界检查。 - 避免使用
.push_back
,因为它会复制数据,因为代理模型会导致很多心痛(更何况是减速)。 - 此外,您可能应该将此函数拆分为一个时间差例程 (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)。
我没有测试过,但我相信上面的方法会比这里的其他方法快得多,尤其是对于大型数据集。