3

我想使用 apply() 函数替换复杂的 for 循环。

我想弄清楚的第一件事是当我只想将它应用于第一列时,如何在具有 100 列的矩阵上使用 apply()。这可能吗?

例如:

for (i in 1:100){ if (runif(1,0,1)<0.01) { a[i,1]<-3-b[i,1] } }

我怎样才能翻译这个来申请?

4

3 回答 3

5

1.apply被设计用于矩阵或数组,而一个特定的列是一个向量并考虑apply家庭函数,而不是更明智地使用mapplyor sapply

# By passing b[, 1]. Two options
v <- sapply(b[, 1], function(x) if(runif(1, 0 ,1) < 0.01) 3 - x else NA)
v <- sapply(b[, 1], function(x) ifelse(runif(1, 0 ,1) < 0.01, 3 - x, NA))
a[!is.na(v), 1] <- v[!is.na(v)]

# By going through indices
a[, 1] <- sapply(1:nrow(b), function(x) 
  if(runif(1, 0, 1) < 0.01) 3 - b[x, 1] else a[x, 1])

# Using mapply to avoid problems related to NAs
mapply(function(x, y) ifelse(runif(1, 0, 1) < 0.01, 3 - y, x), a[, 1], b[, 1])

但是,如果您坚持使用applythen,正如 Roman Luštrik 指出的那样,您必须使其看起来像一个矩阵,即不要通过使用“删除”维度drop = FALSE

a[, 1] <- apply(b[, 1, drop = FALSE], 1, function(x) 
  if(runif(1, 0, 1) < 0.01) 3 - x else NA)
# This returns NAs to make it simpler for now 

2.正如弗洛德尔所说,您必须尽可能尝试使用矢量化。在您的示例中,这是可能的,因为runif可以一次生成nrow(b)数字并且有 的矢量化版本if,即ifelse

a[, 1] <- ifelse(runif(nrow(b), 0, 1) < 0.01,  3 - b[, 1], a[, 1])

最后的方法没有if并且ifelse将是

idx <- runif(100, 0, 1) < 0.01
a[idx, 1] <- 3 - b[idx, 1]
于 2013-08-27T11:04:22.050 回答
3

因为i用在多处,apply不是适合你的例子的工具。相反,您可以使用矢量化代码:

a[, 1] <- if (runif(1,0,1) < 0.01) 3 - b[, 1] else a[, 1]

请注意,如果您希望每一行都有不同的随机结果,那么您需要绘制nrow(a)数字并使用矢量化ifelse

a[, 1] <- ifelse(runif(nrow(a), 0, 1) < 0.01,  3 - b[, 1], a[, 1])
于 2013-08-27T10:51:29.103 回答
2

当然,您需要做的只是传递唯一的一列。

set.seed(357)
my.data <- data.frame(x = runif(10), y = runif(10), z = runif(10))
apply(my.data[, 1, drop = FALSE], MARGIN = 2, FUN = mean)

        x 
0.5234919 
于 2013-08-27T10:50:21.890 回答