所以我想在R中的矩阵上应用一个函数。这对于简单函数非常直观:
> (function(x)x*x)(matrix(1:10, nrow=2))
[,1] [,2] [,3] [,4] [,5]
[1,] 1 9 25 49 81
[2,] 4 16 36 64 100
......但显然我不了解它的所有工作原理:
> m = (matrix(1:10, nrow=2))
> (function(x) if (x %% 3 == 0) { return(NA) } else { return(x+1) })(m)
[,1] [,2] [,3] [,4] [,5]
[1,] 2 4 6 8 10
[2,] 3 5 7 9 11
Warning message:
In if (x == 3) { :
the condition has length > 1 and only the first element will be used
我读到了这个,发现了Vectorize和sapply,它们看起来都很棒,就像我想要的那样,除了它们都将我的矩阵转换成一个列表:
> y = (function(x) if (x %% 3 == 0) { return(NA) } else { return(x+1) })
> sapply(m, y)
[1] 2 3 NA 5 6 NA 8 9 NA 11
> Vectorize(y)(m)
[1] 2 3 NA 5 6 NA 8 9 NA 11
...而我希望将其保留在具有当前尺寸的矩阵中。我怎么能这样做?谢谢!
答案 0 :(得分:19)
y
的情况下直接执行此操作是最佳解决方案。但如果你真的需要来调用一个函数,你可以使用vapply
加快速度。它生成一个不带维度的向量(sapply
,但速度更快),但是您可以使用structure
添加它们:
# Your function (optimized)
y = function(x) if (x %% 3) x+1 else NA
m <- matrix(1:1e6,1e3)
system.time( r1 <- apply(m,1:2,y) ) # 4.89 secs
system.time( r2 <- structure(sapply(m, y), dim=dim(m)) ) # 2.89 secs
system.time( r3 <- structure(vapply(m, y, numeric(1)), dim=dim(m)) ) # 1.66 secs
identical(r1, r2) # TRUE
identical(r1, r3) # TRUE
...正如您所看到的,vapply
方法比apply
方法快3倍... vapply
比sapply
更快的原因是sapply
{1}}必须分析结果,以确定它可以简化为数字向量。使用vapply
,您指定了结果类型(numeric(1)
),因此无需猜测...
UPDATE 我想出了另一种(更短的)保留矩阵结构的方法:
m <- matrix(1:10, nrow=2)
m[] <- vapply(m, y, numeric(1))
您只需使用m[] <-
将新值分配给对象。然后保留所有其他属性(例如dim
,dimnames
,class
等。
答案 1 :(得分:13)
一种方法是在行和列上使用apply
:
apply(m,1:2,y)
[,1] [,2] [,3] [,4] [,5]
[1,] 2 NA 6 8 NA
[2,] 3 5 NA 9 11
您也可以使用下标来完成,因为==
已经过矢量化了:
m[m %% 3 == 0] <- NA
m <- m+1
m
[,1] [,2] [,3] [,4] [,5]
[1,] 2 NA 6 8 NA
[2,] 3 5 NA 9 11
答案 2 :(得分:8)
对于这个具体的例子,你可以做这样的事情
> # Create some fake data
> mat <- matrix(1:16, 4, 4)
> # Set all elements divisible by 3 to NA
> mat[mat %% 3 == 0] <- NA
> # Add 1 to all non NA elements
> mat <- mat + 1
> mat
[,1] [,2] [,3] [,4]
[1,] 2 6 NA 14
[2,] 3 NA 11 15
[3,] NA 8 12 NA
[4,] 5 9 NA 17
答案 3 :(得分:7)
使用ifelse
对Dason和Josh的解决方案略有改进。
mat <- matrix(1:16, 4, 4)
ifelse(mat %% 3 == 0, NA, mat + 1)
[,1] [,2] [,3] [,4]
[1,] 2 6 NA 14
[2,] 3 NA 11 15
[3,] NA 8 12 NA
[4,] 5 9 NA 17