R:在矩阵上应用函数并保持矩阵维数

R:在矩阵上应用函数并保持矩阵维数,r,R,所以我想在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)

所以我想在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

…而我想把它保存在一个矩阵中,它的当前维度。我该怎么做?谢谢

一种方法是在行和列上使用
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

m[m%%3==0]对于这个特定的示例,您可以这样做

> # 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
#创建一些虚假数据
>mat#将所有可被3整除的元素设置为NA
>mat[mat%%3==0]#向所有非NA元素添加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
@Joshua Ulrich(和Dason)有一个很好的答案。不使用函数
y
直接执行是最好的解决方案。但是,如果确实需要调用函数,可以使用
vapply
加快调用速度。它生成一个没有维度的向量(如
sapply
,但速度更快),但您可以使用
结构将它们添加回:

# 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

您只需使用
m[]将新值分配给对象即可。使用
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

mat还可以查看关于apply不同版本的有用帖子:一位同事向我指出了这种方法。它确实满足了我的需要,我也很感激,但似乎真的应该有办法在矩阵上应用预先存在的函数。非常感谢。回想起来,我同意我给出的玩具示例,跳过实际函数是正确的调用,但我真的想知道当它实际上是一个函数时应该如何处理它。(我试图设计一个比我真正处理的更简单的,但显然没有达到目的)无论如何,有时间信息非常有用,因为我也在尝试优化它——谢谢!不错。这将是最快的。使用
rbenchmark
快速检查表明,它比
vapply
解决方案快8倍左右。矢量化总是三叉戟!!
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