一个带有FOR循环的R函数对一个向量进行操作

7

这可能是一个很低级的问题,抱歉。我一直在努力阅读文档并搜索,但没有结果。

我正在尝试在R中创建一个简单的函数,该函数将向量作为参数,使用for循环遍历它并对每个元素进行简单的加法操作。

func1 <- function(vector) {
  vr <- c() ### an empty vector 

  for (i in 1:length(vector)) { 
    vr <- vector[i]+i
  }
}

对我来说,这看起来是正确的,但我总是得到一个空向量。为什么?

你可以在 for 循环中删除 vr <- c()vr <- vector[i]+i,并将 vector[i] <- vector[i] + 1 放入其中。别忘了在函数末尾返回对象 (return(vector) 或者只是 vector)。 - nrussell
2
“function(v) {v + 1:length(v)}”不够吗?你每次循环都在覆盖“vr”。 - tonytonov
2个回答

14
你可以像这样更有效地编写它:
func1 <- function(vector){
    vector + seq_along(vector)
}

这样你就可以利用向量相加的优势。

为了完整起见,让我们对这两种解决方案进行基准测试。以下是一般循环解决方案:

func2 <- function(vector) {
    vr <- c() ### an empty vector 

    for (i in 1:length(vector)) { 
        vr[i] <- vector[i]+i
    }
    vr
}

作为一个升级方案,还有现场解决方案。

func3 <- function(vector) {    
    for (i in 1:length(vector)) { 
        vector[i] <- vector[i]+i
    }
    vector
}

使用microbenchmark,我们可以看到向量化的解决方案是迄今为止最有效的。

vec <- sample(100000, 10000)

library(microbenchmark)
microbenchmark(func1(vec), func3(vec), func2(vec))

Unit: microseconds
       expr       min        lq         mean    median       uq         max neval cld
 func1(vec)    29.998    36.984     44.78312    42.736    44.38     399.006   100  a 
 func3(vec) 12845.823 13666.432  14452.02863 14060.712 14708.53   25025.950   100  a 
 func2(vec) 84898.055 87354.750 110046.26659 88634.566 91193.38 1042819.269   100   b

好的,我明白了。这确实是一个“扇面手掌”:我假设它只会将整个向量转储到vr中...是的,这是一个非常愚蠢的假设。让我忙碌了几个小时,哈哈。非常感谢seq_along函数和benchmark库,确实非常方便! - runlevel0

5
您的代码基本正确,但有两个问题。首先,除非使用return()函数指定返回值,否则R中的函数会返回最后一个表达式。在您的函数中,这是for循环自身。但是,for循环表达式本身不返回任何内容。
其次,最后一行没有在vr上进行索引,因此您正在完全覆盖它,而使用循环的最后一个结果。
因此,我认为以下代码将实现您想要的功能。但同意其他答案中提到的还有更简单的方法可以实现这个功能。
func1 <- function(vector) {
  vr <- c() ### an empty vector 

  for (i in 1:length(vector)) { 
    vr[i] <- vector[i]+i
  }
  vr
}

这将产生以下输出:
> func1(c(1,2))
[1] 2 4

2
好的回答。话虽如此,这并不是你通常在R中编写代码的方式。 - Konrad Rudolph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接