2013-08-27 28 views
2

我想用apply()函数替换复杂的for循环。在R中的矩阵的单列中使用apply()

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

例如:

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

如何翻译这个申请?

回答

2

因为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]) 
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 
4

1。 apply设计用于矩阵或阵列,而一个特定的列是矢量,并考虑apply家庭功能,而不是更明智地使用mapplysapply

# 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那么,作为罗马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如flodel所述,只要有可能,您就必须尝试使用​​矢量化。在您的例子,这是可能的,因为runif可以一次生成nrow(b)数字和有一种if向量化版本,这是ifelse

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

而且没有ififelse最后的办法是

idx <- runif(100, 0, 1) < 0.01 
a[idx, 1] <- 3 - b[idx, 1] 
+1

输出'NA'是避免困难的一种方法。我认为正确的'* apply'工具来复制OP后面的内容将是'mapply'。会给你的答案一个很好的补充。 – flodel