Rcpp中的滚动和函数

Rcpp中的滚动和函数,r,data.table,rcpp,zoo,R,Data.table,Rcpp,Zoo,我目前正在处理一个大数据帧,必须为多个变量创建多个长度的滚动和。我有一个通过data.table的工作方法,但运行单个变量需要相当长的时间,每个变量大约需要50分钟 我花了一些时间来改进脚本以加快速度,但已经没有想法了。我没有C++的经验,但认为RCPP包可能是一种选择。我自己也研究过,但没有找到任何有用的东西 这是一个变量的data.table脚本 df_td <- setDT(df_1, key=c("Match","Name"))[,by=.(Match, Name), paste0

我目前正在处理一个大数据帧,必须为多个变量创建多个长度的滚动和。我有一个通过data.table的工作方法,但运行单个变量需要相当长的时间,每个变量大约需要50分钟

我花了一些时间来改进脚本以加快速度,但已经没有想法了。我没有C++的经验,但认为RCPP包可能是一种选择。我自己也研究过,但没有找到任何有用的东西

这是一个变量的data.table脚本

df_td <- setDT(df_1, key=c("Match","Name"))[,by=.(Match, Name), paste0("Period_", 1:10) 
                                        := mclapply((1:10)*600, function(x) rollsumr(Dist, x, fill = NA))][]

任何关于如何加快这一进程的建议都将不胜感激

我可能已经找到了解决问题的办法。通过从Rcpp添加以下函数


run_sum_v2适合我的data.table行而不是zoo:rollsumr,而且似乎要快得多因为有重叠的和,所以可以重用以前迭代的和。下面是一个使用shift的可能方法

数据:


如果可以缩小数据集,那么在创建这个庞大的数据集之前,您可能想返回一两步?也许你的数据集中有很多零。数据集是由将近400个独立的文件创建的,我已经考虑过将它们保持在列表格式,但这对我来说不是更快吗?关于零,数据基于GPS距离,每0.1秒一次,因此每个文件的开头都有一些零,但每个文件的数量不同。谢谢,但是我上面写的通过Rcpp构建和合并功能的方法似乎对我很有效。尽管我没有经验,但我想知道它是不是一个好的C++解决方案。你可能需要时间看看它是否适合你的需求。大进步!
> dput(head(df_1, 20))
structure(list(Match = c("Bath_A", "Bath_A", "Bath_A", "Bath_A", 
"Bath_A", "Bath_A", "Bath_A", "Bath_A", "Bath_A", "Bath_A", "Bath_A", 
"Bath_A", "Bath_A", "Bath_A", "Bath_A", "Bath_A", "Bath_A", "Bath_A", 
"Bath_A", "Bath_A"), Name = c("Jono Lance", "Jono Lance", "Jono     Lance", 
"Jono Lance", "Jono Lance", "Jono Lance", "Jono Lance", "Jono Lance", 
"Jono Lance", "Jono Lance", "Jono Lance", "Jono Lance", "Jono Lance", 
"Jono Lance", "Jono Lance", "Jono Lance", "Jono Lance", "Jono Lance", 
"Jono Lance", "Jono Lance"), Dist = c(0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Dist_HS = c(0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Dist_SD = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), row.names =    c(NA, 
-20L), class = c("tbl_df", "tbl", "data.frame"))

> str(df_1)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   26533771 obs. of  5     variables:
$ Match  : chr  "Bath_A" "Bath_A" "Bath_A" "Bath_A" ...
$ Name   : chr  "Jono Lance" "Jono Lance" "Jono Lance" "Jono Lance"   ...
$ Dist   : num  0 0 0 0 0 0 0 0 0 0 ...
$ Dist_HS: num  0 0 0 0 0 0 0 0 0 0 ...
$ Dist_SD: num  0 0 0 0 0 0 0 0 0 0 ...
cppFunction('
NumericVector run_sum_v2(NumericVector x, int n) {

        int sz = x.size();

        NumericVector res(sz);

        // sum the values from the beginning of the vector to n 
        res[n-1] = std::accumulate(x.begin(), x.end()-sz+n, 0.0);

        // loop through the rest of the vector
        for(int i = n; i < sz; i++) {
        res[i] = res[i-1] + x[i] - x[i-n];
        }

        // pad the first n-1 elements with NA
        std::fill(res.begin(), res.end()-sz+n-1, NA_REAL);

        return res;
        }
        ')
library(RcppRoll)
DT[, Period_1 := roll_sumr(Dist, 600L, fill=NA), by=.(ID)]
for (n in 2L:10L) {
    DT[, paste0("Period_", n) := {
            x <- get(paste0("Period_", n-1L))
            shift(x, 600L) + Period_1
        },
        by=.(ID)]
}
library(RcppRoll)
DT[, Period_1 := roll_sumr(Dist, 600L, fill=NA), by=.(ID)]
DT[, paste0("Period_", 1L:10L) :=
    Reduce(function(x, y) x + y, shift(Period_1, (1L:9L)*600L), Period_1, accum=TRUE),
    by=.(ID)]
library(data.table)
set.seed(0L)
nsampl <- 6003
nIDs <- 1
DT <- data.table(ID=rep(1:nIDs, each=nsampl), 
    Dist=rnorm(nIDs*nsampl, 1000, 100))