我想用apply()函数替换一个复杂的for循环。
我想弄清楚的第一件事是如何在100列的矩阵上使用apply(),当我只想将它应用于第一列时。这可能吗?
例如:
for (i in 1:100){ if (runif(1,0,1)<0.01) { a[i,1]<-3-b[i,1] } }
如何将其翻译为适用?
答案 0 :(得分:5)
1. apply
设计用于矩阵或数组,而一个特定列是一个向量,并考虑使用apply
族函数,这样更明智地使用mapply
或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])
但是,如果您坚持使用apply
,那么正如RomanLuš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.如flodel所述,只要有可能,你必须尝试使用矢量化。在您的示例中,这是可能的,因为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]
答案 1 :(得分: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])
:
{{1}}
答案 2 :(得分: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