R-我的条件和嵌套for循环花费的时间太长。如何矢量化?

R-我的条件和嵌套for循环花费的时间太长。如何矢量化?,r,R,我为for循环编写了以下代码,其中包含一个条件if语句,其中包括最后10个循环周期,用于搜索逻辑模式的变化,并在true上递增一个计数器: for(ii in 100:sp) { if(start(ii) == 1 && mean(start(ii-11:ii-1)) == 0) { count = count + 1 } } sp值为3560400;这意味着一个300多万次的循环。加载时间非常长,执行循环大约需要40分钟 如

我为for循环编写了以下代码,其中包含一个条件if语句,其中包括最后10个循环周期,用于搜索逻辑模式的变化,并在true上递增一个计数器:

for(ii in 100:sp) 
{
     if(start(ii) == 1 && mean(start(ii-11:ii-1)) == 0)
     {
          count = count + 1
     }
}
sp值为3560400;这意味着一个300多万次的循环。加载时间非常长,执行循环大约需要40分钟

如何使用矢量化优化此代码

谢谢你的帮助

编辑

我在这里包含了我的所有代码,因此每个人都可以看到正在发生的事情:

# store the current directory
initial.dir<-getwd()
# change to the new directory
setwd("H:/R/range")
# load the necessary libraries - sound
library(sound)
library(TTR)

#####################################################
# LOAD .WAV FILE / SET OUTPUT FILE
#####################################################

# set the output file
sink("rangetmp3.out")

# load the dataset
sndSample <- loadSample('range.wav')
FS <- rate(sndSample)
nBits <- bits(sndSample)

# assign sound wave
Y <- sound(sndSample)



#####################################################
# CONSTANTS
#####################################################

#(m/s) speed of light
c <- 3E8 

############################
# |- Radar parameters
############################

#(s) pulse time
Tp <- 20E-3

# number of samples per pulse
N <- Tp*FS

#(Hz) LFM start frequency for example
fstart <- 2260E6

#(Hz) LFM stop frequency for example
fstop <- 2590E6

#(Hz) LFM start frequency for ISM band
fstart <- 2402E6

#(Hz) LFM stop frequency for ISM band
fstop <- 2495E6

#(Hz) transmti bandwidth
BW <- fstop-fstart

#instantaneous transmit frequency
f <- seq(fstart, fstop, length=N/2) 

#range resolution
rr <- c/(2*BW)
max_range <- rr*N/2

#####################################################
# RANGE
#####################################################

############################
# |- The input appears to be inverted
############################

trig <- -1*Y[1,]
s <- -1*Y[2,]

#reset Y
#Y = 0

############################
# |- Parse the data here by triggering off rising edge of sync pulse
############################

# reset counter / threshold
count <- 0
thresh <- 0

# assign logical vector that meets thresh

start <- (trig > thresh)

sp <- NROW(start)-N

for(ii in 100:sp) 
{
     if(start(ii) == 1 && mean(start(ii-11:ii-1)) == 0)
     {
          count = count + 1
     }
}
您可以在一行两行中完成,如下所示:

library(TTR)
shiftIndx <- c(6:length(start), 1:5)
count <- sum(start == 1  &  SMA(start, n=11)[shiftIndx] == 0, na.rm=TRUE)

下面是一些基准测试(在编辑添加'shiftIndx'之前)
种子(7)
对于(N在10^(6:8)){
cat(“N是:,N,“\N”)
开始您可以在一行两行中完成,如下所示:

library(TTR)
shiftIndx <- c(6:length(start), 1:5)
count <- sum(start == 1  &  SMA(start, n=11)[shiftIndx] == 0, na.rm=TRUE)

下面是一些基准测试(在编辑添加'shiftIndx'之前)
种子(7)
对于(N在10^(6:8)){
cat(“N是:,N,“\N”)


开始你的意思是使用函数
start()
还是有一个名为
start
的向量/列表,你的意思是对它进行索引,即
start[ii]
?另外,看看
?:“
我相信你需要两对括号,因此你正在计算的平均值是一组完全不同的数字:使用另一个
(ii-11):(ii-1)
或者更好的是,
ii-(11:1)
。最后一个参数不需要,但有助于可读性它必须是一个索引,因为(据我所知)
start()
将为任何整数返回
11
。因此它代表
if()的第一部分
在任何情况下都是正确的,但我认为在每次迭代时都会发出警告!大家好,非常感谢你们的回答和问题。@Resso,看起来
trig
是一个一维向量,因此
start
也将是。请看这一行:
trig您想使用函数
start()
或者你有一个名为
start
的向量/列表,你想索引它吗,即
start[ii]
?另外,看看
?:“
我认为你需要两对括号,因此你计算的平均值是一组完全不同的数字:使用它们(ii-11):(ii-1)
或者更好的方法是,
ii-(11:1)
。最后一个参数不是必需的,但有助于可读性。它必须是一个索引,因为(据我所知)
start()
将为任何整数返回
1
。因此它代表
if()的第一部分
在任何情况下都是正确的,但我认为在每次迭代时都会发出警告!大家好,非常感谢你们的回答和问题。@Resso,看起来
trig
是一个一维向量,因此
start
也将是。请看这行:
trig感谢@flodel的帮助。我认为第二个参数是错误的sing只是我粘贴更正时的一个输入错误,但已被清除。@Resso,
0
是否可能是正确的计数?为什么不尝试创建一个较小的人工数据集,手动检查正确的输出,然后用它来测试代码。@flodel,你是对的,我的MA已关闭。但我不确定它是否正确s乘以1。我认为它必须被移位
floor(11/2)
@Resso,输出不是输出的全部。使用
tail(,12)
查看最后12个值sop正在寻找类似
sum(tail(start==1和runSum(start,n=12)=1),-99)的东西
。还有@Ricardo,你的解决方案又产生了NA,为什么不测试你的代码呢?谢谢@flodel的帮助。我想第二个参数丢失的只是我粘贴更正时的一个输入错误,但已经被清除了。@Resso,
0
是否可能是正确的计数?你为什么不尝试创建一个较小的人工数据集呢你可以手动检查正确的输出,然后用它来测试代码。@flodel,你是对的,我的MA是关闭的。但是我不确定它是1。我想它必须移动
下限(11/2)
@Resso,输出不是输出的全部。使用
尾部(,12)
要查看最后12个值,SOP正在查找类似于
sum(tail(start==1&runSum(start,n=12)==1),-99))
。并且@Ricardo,您的解决方案再次生成NA,为什么不测试您的代码?
## this will give you a logical vector of T/F
##    whose length will be equal to length of start
start == 1

## This part give you a smiple moving average of every 11 numbers
SMA(start, n=11)

## We need to shift these over so that they are centered properly. 
##   `shiftIndx` takes the first `floor(11/2)` MA's and puts them at the tail. 
##    (notice that these will be NA.)
shiftIndx <- c(6:length(start), 1:5)
SMA(start, n=11)[shiftIndx]

## .. checking if it is equal to 0 will give you another T/F vector, 
##     also of length equal to the length of start
SMA(start, n=11)[shiftIndx]  == 0

## Then combining the T/F vectors using `&` gives another T/F vector 
##   of the same length, but is TRUE only where _both_ of the original 
##   vectors are TRUE
(start == 1)   &   (SMA(start, n=11)[shiftIndx] == 0)

## Taking the `sum(.)` of a logical vector is the equivalent of counting
##    how many TRUE values are in the vector. 
## Snce you are incrementing `count` every time both conditional statements are TRUE, 
##    the final value of `count` will be the same as the sum below
sum( (start == 1)   &   (SMA(start, n=11)[shiftIndx] == 0), na.rm=TRUE)
And here are some benchmarks (before the edit of adding `shiftIndx`)

set.seed(7)
for (N in 10^(6:8)) {
  cat("N is: ", N, "\n")
  start <- round(rnorm(N, 0, 10))    
  print(system.time(
    count <- sum(start == 1  &  SMA(start, n=11) == 0, na.rm=TRUE)
  ))
  cat("count is ", count, "\n", rep("~", 14), "\n\n", sep="")
}

## OUTPUT: 

N is:  1e+06 
   user  system elapsed 
  0.059   0.021   0.081 
count is 485
~~~~~~~~~~~~~~

N is:  1e+07 
   user  system elapsed 
  0.578   0.195   0.768 
count is 4889
~~~~~~~~~~~~~~

N is:  1e+08 
   user  system elapsed 
  7.808   5.716  19.392 
count is 49737
~~~~~~~~~~~~~~