R中循环的替代方案

R中循环的替代方案,r,for-loop,R,For Loop,可能重复: 我有几个关于循环的问题。我知道R在矢量化计算中工作得更快,我想修改下面的代码来利用这一点。在论坛上查看其他一些答案时,sapply函数似乎能够替换内部for循环,但我正在生成一个零向量,因此存在一个错误。陶仍然是1000,我认为这是造成问题的原因 我主要关心的是速度,因为我需要围绕整个算法创建一个循环,并以不同的V和n大小绘制曲线,以便进行进一步的分析 谢谢你的帮助 备选循环 tao=1000 L=(道-1) n=10 V=5 I=10000 V_s=矩阵(形式(I),I,1) V

可能重复:

我有几个关于循环的问题。我知道R在矢量化计算中工作得更快,我想修改下面的代码来利用这一点。在论坛上查看其他一些答案时,sapply函数似乎能够替换内部for循环,但我正在生成一个零向量,因此存在一个错误。陶仍然是1000,我认为这是造成问题的原因

我主要关心的是速度,因为我需要围绕整个算法创建一个循环,并以不同的V和n大小绘制曲线,以便进行进一步的分析

谢谢你的帮助

备选循环

tao=1000
L=(道-1)
n=10
V=5
I=10000
V_s=矩阵(形式(I),I,1)
V_b=矩阵(形式(I),I,1)

signal假设显式循环是正确的计算,请尝试以下操作:

 signal[j]<- signal[j] + 
              sapply((j-n+1):j, 
                   FUN = function(iter){ 
                           abs(V_s[iter] - V_b[iter])
                   }, V_s = V_s, V_b = V_b)

signal[j]矢量化计算并不总是意味着使用*apply函数

例如,您可以通过使用向量索引替换第二个For循环来简化和加速事情:

for(j in (n:L)){
  sel <- (j-n+1):j
  signal[j] <- sum(abs(V_s[sel] - V_b[sel])) / (n*V)
}
而对于
for
循环,它是:

utilisateur     système      écoulé 
       0.06        0.00        0.06 

顺便说一句,你不应该用
tao
这个名字来表示两种不同的东西。

使用过滤器,你甚至可以在没有任何循环的情况下进行计算(而
sapply
只不过是一个隐藏的循环)

这正是卷积滤波器所做的——将一些值相加——以一般形式乘以一些权重。作为权重,我们为所有值选择
1/(n*V)
,这与您在外部循环中执行的标准化相对应。最后一个参数,
sides=1
只是告诉过滤器只从过去获取值(
sides=2
意味着
sum(absdif[(j-n/2):(j+n/2)])

最后一行只填充开头的
NA
值(过滤器没有足够的数据来计算总和-这等于跳过第一个
n
值)

最后,一些时间安排:

您的完整循环解决方案:

   User      System       total 
  0.037       0.000       0.037 
朱巴问题的解决办法:

   User      System       total 
  0.007       0.000       0.008 
使用过滤器的解决方案:

   User      System       total 
  0.000       0.000       0.001 
请注意,过滤器的概念是非常好的研究,可以做得非常快

编辑: 如
?filter
中所述,R不使用标准
filter
命令的快速傅里叶变换。通常,FFT是实现卷积的最有效方法。但是,甚至可以通过将filter命令替换为

signal <- convolve(absdif[1:L], rep(1/(n*V), n), type='filter')

signal是否有理由使用矩阵而不是向量,而V_s、V_b和signal似乎只有一列?如果将
browser()
放入for(tao)循环中,您将能够检查函数的内部工作,并查看发生了什么。@juba,我在后面的方法中使用了矩阵格式,但本质上是这样的,这是一个矢量。关于加速R代码的一般建议是:完全正确。矢量化几乎总能提高速度
*apply
函数很少使用。这大大缩短了处理时间,感谢您的帮助和输入。很好的解决方案,不知道如何使用
filter()
+1,虽然filter也可能是一个伪装的循环…@PaulHiemstra可能,但似乎是一个非常有效的循环:)@Paul Well,矢量化始终只是一个隐藏的循环,但其间有不同的优化步骤。过滤器的优化水平应与
abs
操作符的优化水平相同。但是,在思考的同时,我们仍然可以做得更好。请稍后查看我的编辑。感谢您的回答,我运行了您的建议并收到了与预期不同的输出。我应该用两个for循环替换您的解决方案?
signal[j] <- sum(absdif[j-n+1:j])
   User      System       total 
  0.037       0.000       0.037 
   User      System       total 
  0.007       0.000       0.008 
   User      System       total 
  0.000       0.000       0.001 
signal <- convolve(absdif[1:L], rep(1/(n*V), n), type='filter')