为什么apply函数返回的值不同于循环?

时间:2019-07-30 15:31:00

标签: r apply

我正在尝试将应用函数隐藏到嵌套循环中,以便在R之外的软件中使用。我编写的循环看起来很相似,但是返回的值与应用函数略有不同。

我一直尝试调整索引,但仍然无法返回相同的值。

require(MASS)


# set up grid
B <- 5
co <- seq(0, 1, length=B)
Z <- cbind(rep(co, each=B), rep(co, times=B))



# long hand euclidean distance
x <- Z[,1]
y <- Z[,2]
d <- matrix(NA, nrow = nrow(Z), ncol = nrow(Z))
N <- nrow(Z)
for(i in 1:N){
  for(j in 1:N){
    d[i,j] <- sqrt((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]))
  }
}

# generate a value for each pixel
cov <- MASS::mvrnorm(1, mu = rep(0, nrow(Z)), Sigma = exp(-d/0.25))

# calculate weights of each pixel
# apply
applyW <- apply(d, 1, function(x) {
  w0 <- exp(-x^2 / (2*0.3 * 0.3))
  w0[which.min(x)] <- 0
  w <- w0/sum(w0)
  sum(cov * w)
})


# for loop approach
w0 <- matrix(NA, ncol = ncol(d), nrow = nrow(d))
w <- matrix(NA, ncol = ncol(d), nrow = nrow(d))
loopW <- c()
for(i in 1:nrow(d)){
  for(j in 1:ncol(d)){
    w0[i, j] <- exp(-(d[i,j] * d[i,j]) / (2 * 0.3 * 0.3))
    w0[which.min(w0)] <- 0
  }
  w[i, ] <- w0[i ,]/sum(w0[i,])
  loopW[i] <- sum(cov * w[i,])
}
# check the values
cbind(applyW, loopW)

我期望applyW和loopW是相同的值,但是我找不到。值相似,但不相同。这是一个舍入错误还是代码中有错误?

1 个答案:

答案 0 :(得分:1)

我还没有花时间来确切地了解您要完成的工作,但是代码的这两部分在执行方面并不匹配:

在您的申请中:

w0[which.min(x)] <- 0

这里w0是一个向量(即一行),您正在用0替换该向量中的最小值。按照apply(MARGIN = 1)分别对每一行进行此操作。

但是,在循环中您有:

w0[which.min(w0)] <- 0

这里w0是一个矩阵,每次移动到下一个矩阵元素时,代码中w0[which.min(w0)] <- 0所在的位置连续用0替换最小值(即,不按行在您的apply()中。

如果将此行移到内循环之外并进行一些调整以匹配apply(),则会得到相同的值:

require(MASS)

# set up grid
B <- 5
co <- seq(0, 1, length=B)
Z <- cbind(rep(co, each=B), rep(co, times=B))

# long hand euclidean distance
x <- Z[,1]
y <- Z[,2]
d <- matrix(NA, nrow = nrow(Z), ncol = nrow(Z))
N <- nrow(Z)
for(i in 1:N){
  for(j in 1:N){
    d[i,j] <- sqrt((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]))
  }
}

# generate a value for each pixel
cov <- MASS::mvrnorm(1, mu = rep(0, nrow(Z)), Sigma = exp(-d/0.25))

# calculate weights of each pixel
# apply
applyW <- apply(d, 1, function(x) {
  w0 <- exp(-x^2 / (2*0.3 * 0.3))
  w0[which.min(x)] <- 0
  w <- w0/sum(w0)
  sum(cov * w)
})


# for loop approach
w0 <- matrix(NA, ncol = ncol(d), nrow = nrow(d))
w <- matrix(NA, ncol = ncol(d), nrow = nrow(d))
loopW <- c()
for(i in 1:nrow(d)){
  for(j in 1:ncol(d)){
    w0[i, j] <- exp(-(d[i,j] * d[i,j]) / (2 * 0.3 * 0.3))
    #w0[which.min(w0)] <- 0 move this outside inner loop
  }
  w0[i, which.min(d[i, ])] <- 0 # and make some tweaks to match the apply
  w[i, ] <- w0[i ,]/sum(w0[i,])
  loopW[i] <- sum(cov * w[i,])
}
# check the values
output <- cbind(applyW, loopW)
output <- cbind(output, "dif" = output[, "applyW"] - output[, "loopW"])
output

产生:

           applyW       loopW dif
 [1,]  0.62023939  0.62023939   0
 [2,]  0.45082535  0.45082535   0
 [3,]  0.07066739  0.07066739   0
 [4,]  0.01518537  0.01518537   0
 [5,]  0.13383600  0.13383600   0
 [6,]  0.52896297  0.52896297   0
 [7,]  0.38474014  0.38474014   0
 [8,]  0.23321748  0.23321748   0
 [9,]  0.07092092  0.07092092   0
[10,] -0.04388823 -0.04388823   0
[11,]  0.46926149  0.46926149   0
[12,]  0.39166724  0.39166724   0
[13,]  0.12309979  0.12309979   0
[14,] -0.04778011 -0.04778011   0
[15,]  0.10359100  0.10359100   0
[16,]  0.41273927  0.41273927   0
[17,]  0.33122926  0.33122926   0
[18,] -0.10115094 -0.10115094   0
[19,] -0.15051985 -0.15051985   0
[20,] -0.23035539 -0.23035539   0
[21,]  0.37065262  0.37065262   0
[22,] -0.24497145 -0.24497145   0
[23,] -0.04993695 -0.04993695   0
[24,] -0.24990339 -0.24990339   0
[25,] -0.27183745 -0.27183745   0