我有带有数值的向量。例如:
inVector <- c(2, -10, 5, 34, 7)
我需要转换它,以便当我遇到一个负元素时,该负元素与后续元素相加,直到将总和变为正的元素:
outVector <- c(2, 0, 0, 29, 7)
负元素将为零,以便总和保持不变。所以元素 2 和 3 将为零,第四个元素等于 29 = -10 + 5 + 34。我尝试了这样的 for 循环解决方案:
outVector <- numeric(length = length(inVector))
for(i in 1:length(inVector)) {
outVector <- inVector
outVector[i] <- ifelse(outVector[i] < 0, 0, outVector[i])
outVector[i + 1] <- ifelse(outVector[i] == 0, sum(inVector[i:(i+1)]), outVector[i + 1])
outVector <- outVector[1:length(inVector)]
}
但这没有用。但是,我最感兴趣的是也适用于 dplyr 管道的解决方案。
最佳答案
试试这个:
MakeNonNeg <- function(v) {
size <- length(v)
myOut <- as.numeric(v)
if (size > 1L) {
for (i in 1:(size-1L)) {
if (myOut[i] >= 0) {next}
myOut[i+1L] <- myOut[i]+myOut[i+1L]
myOut[i] <- 0
}
}
myOut
}
MakeNonNeg(inVector)
[1] 2 0 0 29 7
下面是一个更奇特的例子:
set.seed(4242)
BigVec <- sample(-40000:100000, 100000, replace = TRUE)
gmp::sum.bigz(BigVec)
Big Integer ('bigz') :
[1] 2997861106
t3 <- MakeNonNeg(BigVec)
gmp::sum.bigz(t3)
Big Integer ('bigz') :
[1] 2997861106
BigVec[1:20]
[1] 98056 8680 -7814 53620 58390 90832 74970 -16392 52648 83779 -17229 38484 -36589 75156 71200 95968 -11599 57705
[19] 19209 -21596
t3[1:20]
[1] 98056 8680 0 45806 58390 90832 74970 0 36256 83779 0 21255 0 38567 71200 95968 0 46106 19209 0
这是我的系统信息:
sessionInfo()
R version 3.3.0 (2016-05-03)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
以下是禁用 JIT 的两个函数的时序。
microbenchmark(
makeNonNeg = MakeNonNeg(BigVec),
zeroElement = zeroElement(BigVec),
times=10)
Unit: milliseconds
expr min lq mean median uq max neval
makeNonNeg 254.1255 255.8430 267.9527 258.6369 277.0222 303.6516 10
zeroElement 152.0358 164.7988 175.3191 166.4948 198.3855 209.8739 10
启用
JIT
后,我们对 makeNonNeg
获得了非常不同的结果。然而,zeroElement
的结果并没有太大变化(我认为由于 Reduce
是函数的主要部分,并且它已经是字节码,所以没有太大的改进空间)。library(compiler)
enableJIT(3)
[1] 0
microbenchmark(
makeNonNeg = MakeNonNeg(BigVec),
zeroElement = zeroElement(BigVec),
times=10)
Unit: milliseconds
expr min lq mean median uq max neval
makeNonNeg 11.20514 11.55366 12.76953 11.84655 12.20554 20.60036 10
zeroElement 144.15123 149.33591 163.66421 157.34711 176.20139 198.57268 10
因此,禁用
JIT
后,zeroElement
的速度提高了约 50%,而启用 JIT
时,MakeNonNeg
的速度提高了约 13 倍。关于R:数值向量的条件求和,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39103071/