在矩阵的每个元素上应用函数

时间:2017-06-15 15:44:00

标签: r matrix apply

去年,当参数根据函数同时改变值时,我使用code产生三变量正态分布的累积概率的不同值。我用了这段代码:

library(mvtnorm)
Y <- mapply(function(x,y,z) 
  pmvnorm(mean  = c(18, 12.72, (18*(x+y) +12.72*z)),
          sigma = {
            s1 <- matrix(c(5.7, 0, 5.7*(x+y),
                           0, 30.38, 30.38*z,
                           5.7*(x+y), 30.38*z, 5.7*(x+y)^2+30.38*(z)^2),
                         3)
            replace(s1,s1==0, 1e-20)
          },
          lower = c(15, -Inf, p+15*y),
          upper = c(Inf, 15, Inf)),
  m1, m2, m3)

其中m1,m2,m3(与x,y和z相关)是已定义的向量。由于它们是1x10向量,因此代码生成向量1x10。

现在如果m1,m2和m3是矩阵怎么办?我使用以下代码生成三个矩阵10x36:

a <- 5
b <- 5
vals <- rep(0:a, (b+1))
x <- rep(1:(a+b), ((a+1)*(b+1)))
c <- matrix(pmin(x, vals[rep(1:((a+1)*(b+1)), each = (a+b))]), nrow = (a+b))
m1 <- c
d1 <- matrix(rep(c(1:(a+b)), ((a+1)*(b+1))), ncol=((a+1)*(b+1)), nrow=(a+b),      byrow=F)
d2 <- matrix(rep(rowSums(expand.grid(0:a, 0:b)), (a+b)), ncol=((a+1)*(b+1)),  nrow=(a+b), byrow=T)
d3 <- pmax((d1-d2),0)
d4 <- matrix(rep(0:a, b+1), ncol=((a+1)*(b+1)), nrow=(a+b), byrow=T)
d5 <- a-d4
d6 <- pmin(d3,d5)
d7 <- matrix(nrow = (a+b), ncol = ((a+1)*(b+1)))
for (i in 1:(a+b)) {
  for (j in 1:((a+1)*(b+1))) {
    d7[i,j] <- a
  }
}
d8 <- pmin(d7,d1)
d <- d6-d8
m2 <- d
e1 <- pmin(d1,d2)
e2 <- e1-d4
e3 <- matrix(nrow = (a+b), ncol = ((a+1)*(b+1)))
for (i in 1:(a+b)) {
  for (j in 1:((a+1)*(b+1))) {
    e3[i,j] <- 0
  }
}
e <- pmax(e2, e3)
m3 <- e
r <- 0.04
k <- rep(rowSums(expand.grid(0:a, 0:b)))
p <- k*(15*(1-r)^(k-1))
p <- t(matrix(rep(p,(a+b)), ncol=(a+b), nrow=((a+1)*(b+1))))

现在我想生成一个矩阵10x36,其中每个元素是三变量正态分布的累积概率值,其中均值和协方差矩阵取决于矩阵m1 m2和m3的元素。 我再次尝试使用代码:

Y <- mapply(function(x,y,z) 
  pmvnorm(mean  = c(18, 12.72, (18*(x+y) +12.72*z)),
          sigma = {
            s1 <- matrix(c(5.7, 0, 5.7*(x+y),
                           0, 30.38, 30.38*z,
                           5.7*(x+y), 30.38*z, 5.7*(x+y)^2+30.38*(z)^2),
                         3)
            replace(s1, s1==0, 1e-20)
          },
          lower = c(15, -Inf, p+15*y),
          upper = c(Inf, 15, Inf)),
  m1, m2, m3)

但是我收到以下错误:

Error in checkmvArgs(lower = lower, upper = upper, mean = mean, corr = corr,     : 
  at least one element of ‘lower’ is larger than ‘upper’
Warning message:
In cbind(lower, upper, mean) :
number of rows of result is not a multiple of vector length (arg 2).

错误在哪里?

1 个答案:

答案 0 :(得分:1)

由于m1m2m3 p的尺寸均为10x36,我推断您有意每次使用p的每个单独值而不是整个矩阵。例如,如果您单步调用pmvnorm,则会看到:

Y <- mapply(function(x,y,z) {
  browser()
  pmvnorm(mean  = c(18, 12.72, (18*(x+y) +12.72*z)),
          sigma = {
            s1 <- matrix(c(5.7, 0, 5.7*(x+y),
                           0, 30.38, 30.38*z,
                           5.7*(x+y), 30.38*z, 5.7*(x+y)^2+30.38*(z)^2),
                         3)
            replace(s1, s1==0, 1e-20)
          },
          lower = c(15, -Inf, p+15*y),
          upper = c(Inf, 15, Inf))
}, m1, m2, m3)
# debug at c:/Users/r2/AppData/Local/Temp/foo.R!12268ZNM#3: pmvnorm(mean = c(18, 12.72, (18 * (x + y) + 12.72 * z)), sigma = {
#     s1 <- matrix(c(5.7, 0, 5.7 * (x + y), 0, 30.38, 30.38 * z, 
#         5.7 * (x + y), 30.38 * z, 5.7 * (x + y)^2 + 30.38 * (z)^2), 
#         3)
#     replace(s1, s1 == 0, 1e-20)
# }, lower = c(15, -Inf, p + 15 * y), upper = c(Inf, 15, Inf))
# Browse[2]> 
x
# [1] 0

这是预期的。

# Browse[2]> 
dim(p)
# [1] 10 36

我认为这应该是:

# Browse[2]>
p
# [1] 0

在这种情况下,您可以通过将p添加到参数列表来开始解决问题:

pm <- p   # 'pm' is 'p-matrix' (?)
rm(p)

(我这样做是为了消除p调用内外mapply的含糊不清。无论如何它都有用,但是对你不确定的关闭进行排查正在使用哪个变量实例可能令人沮丧,当然也不直观。)

set.seed(2)
Y <- mapply(function(x,y,z,p)
  pmvnorm(mean  = c(18, 12.72, (18*(x+y) +12.72*z)),
          sigma = {
            s1 <- matrix(c(5.7, 0, 5.7*(x+y),
                           0, 30.38, 30.38*z,
                           5.7*(x+y), 30.38*z, 5.7*(x+y)^2+30.38*(z)^2),
                         3)
            replace(s1, s1==0, 1e-20)
          },
          lower = c(15, -Inf, p+15*y),
          upper = c(Inf, 15, Inf)),
  m1, m2, m3, pm)

您将看到的一个问题是mapply已经返回了一个向量。

head(Y)
# [1] 0.2957254 0.2957254 0.2957254 0.2957254 0.2957254 0.2957254
length(Y)
# [1] 360
dim(Y)
# NULL

可以通过为输入变量指定相同的维度来解决此问题。 (由于您使用默认的matrix来调用byrow=FALSE,因此按原样运行。如果您已完成byrow=TRUE,则需要在此进行调整。)

dim(Y) <- dim(m1)
dim(Y)
# [1] 10 36
Y[1:4,1:5]
#           [,1]      [,2]      [,3]      [,4]      [,5]
# [1,] 0.2957254 0.2957254 0.0000000 0.0000000 0.0000000
# [2,] 0.2957254 0.2957254 0.5914508 0.0000000 0.0000000
# [3,] 0.2957254 0.2957254 0.5914508 0.5914508 0.0000000
# [4,] 0.2957254 0.2957254 0.5914508 0.5914508 0.5914508