你好我试图操纵数字的列表,我想for循环这样做没有,使用快速本地操作R的伪代码操作是:
默认情况下,起始总为100(对于零内的每个块)
从最初的零到下一个零,当下的累计跌幅超过2%与零替换所有后续的数字。
做到这一点远远零中的所有数字块
累计总和重置为每次100
例如,如果下面是我的数据:
d <- c(0,0,0,1,3,4,5,-1,2,3,-5,8,0,0,-2,-3,3,5,0,0,0,-1,-1,-1,-1);
结果将是:
0 0 0 1 3 4 5 -1 2 3 -5 0 0 0 -2 -3 0 0 0 0 0 -1 -1 -1 0
目前,我有一个for循环的实现,但因为我的矢量是很长的,性能是可怕的。
提前致谢。
这里是一个正在运行的代码示例:
d <- c(0,0,0,1,3,4,5,-1,2,3,-5,8,0,0,-2,-3,3,5,0,0,0,-1,-1,-1,-1);
ans <- d;
running_total <- 100;
count <- 1;
max <- 100;
toggle <- FALSE;
processing <- FALSE;
for(i in d){
if( i != 0 ){
processing <- TRUE;
if(toggle == TRUE){
ans[count] = 0;
}
else{
running_total = running_total + i;
if( running_total > max ){ max = running_total;}
else if ( 0.98*max > running_total){
toggle <- TRUE;
}
}
}
if( i == 0 && processing == TRUE )
{
running_total = 100;
max = 100;
toggle <- FALSE;
}
count <- count + 1;
}
cat(ans)
我不知道如何将循环转化为矢量操作。 然而,也有大的性能提升两个相当容易的选择。 第一个是简单地把你圈成R
功能,并使用compiler
包进行预编译它。 第二个稍微复杂一些的选择是你的翻译R
环路成c++
回路,并使用Rcpp
包将它链接到R
功能。 然后调用一个R
它传递给功能c++
代码,其是快速。 我同时显示这些选项和时间。 我想非常感谢亚历山大Bujard从RCPP群发,谁与指针的问题我不明白帮助我的帮助。
首先,这里是你的R
环路的功能, foo.r
。
## Your R loop as a function
foo.r <- function(d) {
ans <- d
running_total <- 100
count <- 1
max <- 100
toggle <- FALSE
processing <- FALSE
for(i in d){
if(i != 0 ){
processing <- TRUE
if(toggle == TRUE){
ans[count] <- 0
} else {
running_total = running_total + i;
if (running_total > max) {
max <- running_total
} else if (0.98*max > running_total) {
toggle <- TRUE
}
}
}
if(i == 0 && processing == TRUE) {
running_total <- 100
max <- 100
toggle <- FALSE
}
count <- count + 1
}
return(ans)
}
现在,我们可以加载compiler
包和编译功能,并调用它foo.rcomp
。
## load compiler package and compile your R loop
require(compiler)
foo.rcomp <- cmpfun(foo.r)
这是所有需要的编译路径。 这是所有R
显然很容易。 现在的c++
方法,我们使用Rcpp
包还有inline
包,它可以让我们“内联”的c++
代码。 也就是说,我们不必做一个源文件和编译它,我们只是将其包含在R
代码和汇编为我们处理。
## load Rcpp package and inline for ease of linking
require(Rcpp)
require(inline)
## Rcpp version
src <- '
const NumericVector xx(x);
int n = xx.size();
NumericVector res = clone(xx);
int toggle = 0;
int processing = 0;
int tot = 100;
int max = 100;
typedef NumericVector::iterator vec_iterator;
vec_iterator ixx = xx.begin();
vec_iterator ires = res.begin();
for (int i = 0; i < n; i++) {
if (ixx[i] != 0) {
processing = 1;
if (toggle == 1) {
ires[i] = 0;
} else {
tot += ixx[i];
if (tot > max) {
max = tot;
} else if (.98 * max > tot) {
toggle = 1;
}
}
}
if (ixx[i] == 0 && processing == 1) {
tot = 100;
max = 100;
toggle = 0;
}
}
return res;
'
foo.rcpp <- cxxfunction(signature(x = "numeric"), src, plugin = "Rcpp")
现在我们可以测试我们得到预期的结果:
## demonstrate equivalence
d <- c(0,0,0,1,3,4,5,-1,2,3,-5,8,0,0,-2,-3,3,5,0,0,0,-1,-1,-1,-1)
all.equal(foo.r(d), foo.rcpp(d))
最后,创建一个更大的版本d
重复它10E4倍。 然后,我们可以运行三个不同的函数,纯R
代码,编译R
代码,和R
功能链接到c++
代码。
## make larger vector to test performance
dbig <- rep(d, 10^5)
system.time(res.r <- foo.r(dbig))
system.time(res.rcomp <- foo.rcomp(dbig))
system.time(res.rcpp <- foo.rcpp(dbig))
这在我的系统上,给出了:
> system.time(res.r <- foo.r(dbig))
user system elapsed
12.55 0.02 12.61
> system.time(res.rcomp <- foo.rcomp(dbig))
user system elapsed
2.17 0.01 2.19
> system.time(res.rcpp <- foo.rcpp(dbig))
user system elapsed
0.01 0.00 0.02
编译后的R
代码需要大约1/6的时间的未编译R
代码只服用2秒上的250万的矢量操作。 在c++
代码是快几个数量级甚至然后编译R
仅需0.02秒完成代码。 除了初始设置,对于基本循环的语法是几乎相同的R
和c++
这样你就不会甚至失去清晰度。 我怀疑,即使部分或全部的循环可能会在被矢量R
你会疼压制击败的性能R
挂钩函数c++
。 最后,只是为了证明:
> all.equal(res.r, res.rcomp)
[1] TRUE
> all.equal(res.r, res.rcpp)
[1] TRUE
不同的函数返回相同的结果。