我正在尝试加速获取时间序列数据的代码并将其限制为最大值,然后将其向前拉伸,直到原始数据和“拉伸”数据的总和相同为止。
我有一个更复杂的版本需要6个小时才能在100k行上运行。我不认为这是可矢量化的,因为它使用在先前行上计算的值 - 这是正确的吗?
x <- c(0,2101,3389,3200,1640,0,0,0,0,0,0,0)
dat <- data.frame(x=x,y=rep(0,length(x)))
remainder <- 0
upperlimit <- 2000
for(i in 1:length(dat$x)){
if(dat$x[i] >= upperlimit){
dat$y[i] <- upperlimit
} else {
dat$y[i] <- min(remainder,upperlimit)
}
remainder <- remainder + dat$x[i] - dat$y[i]
}
dat
我知道你可以使用ifelse
,但我不认为cumsum
可以用来推进余下的事项 - apply
据我所知也无济于事。我是否需要诉诸Rcpp
?非常感谢你。
答案 0 :(得分:0)
我继续在Rcpp
中实施此功能,并对R
功能进行了一些调整:
require(Rcpp);require(microbenchmark);require(ggplot2);
limitstretchR <- function(upperlimit,original) {
remainder <- 0
out <- vector(length=length(original))
for(i in 1:length(original)){
if(original[i] >= upperlimit){
out[i] <- upperlimit
} else {
out[i] <- min(remainder,upperlimit)
}
remainder <- remainder + original[i] - out[i]
}
out
}
Rcpp
功能:
cppFunction('
NumericVector limitstretchC(double upperlimit, NumericVector original) {
int n = original.size();
double remainder = 0.0;
NumericVector out(n);
for(int i = 0; i < n; ++i) {
if (original[i] >= upperlimit) {
out[i] = upperlimit;
} else {
out[i] = std::min<double>(remainder,upperlimit);
}
remainder = remainder + original[i] - out[i];
}
return out;
}
')
测试它们:
x <- c(0,2101,3389,3200,1640,0,0,0,0,0,0,0)
original <- rep(x,20000)
upperlimit <- 2000
system.time(limitstretchR(upperlimit,original))
system.time(limitstretchC(upperlimit,original))
分别产生80.655和0.001秒。原生R
对此非常不利。但是,我运行microbenchmark
(使用较小的矢量)并得到了一些令人困惑的结果。
res <- microbenchmark(list=
list(limitstretchR=limitstretchR(upperlimit,rep(x,10000)),
limitstretchC=limitstretchC(upperlimit,rep(x,10000))),
times=110,
control=list(order="random",warmup=10))
print(qplot(y=time, data=res, colour=expr) + scale_y_log10())
boxplot(res)
print(res)
如果您要运行它,您会看到两种功能几乎相同的结果。这是我第一次使用microbenchmark
,任何提示?