首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rcpp中的滚动和函数

Rcpp中的滚动和函数
EN

Stack Overflow用户
提问于 2018-12-03 00:47:40
回答 2查看 511关注 0票数 0

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

我花了一些时间来改进这个脚本,以加快它的速度,但是我的想法已经用完了。我没有C++方面的经验,但我认为Rcpp包可能是一种选择。我已经亲自调查过了,但还没有想出任何有用的东西。

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

代码语言:javascript
复制
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))][]

我使用过parallel::mclapply,它帮助了我,但它仍然需要相当长的时间才能工作。

代码语言:javascript
复制
> 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 ...

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-03 01:28:00

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

代码语言:javascript
复制
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;
        }
        ')

run_sum_v2适合于我的data.table行,而不是zoo:rollsumr,而且速度似乎要快得多(<1分钟)。需要对最终数据进行一些检查,但到目前为止看起来很有希望。

已经花了两个多小时的脚本到<20秒,所以我对这种方法很满意,除非它有任何问题?

票数 0
EN

Stack Overflow用户

发布于 2018-12-03 01:44:57

由于存在重叠和,所以可以重用以前迭代中的和。下面是一种使用shift的可能方法

代码语言:javascript
复制
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)]
}

使用Reduce替换循环:

代码语言:javascript
复制
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)]

数据:

代码语言:javascript
复制
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))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53586097

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档