首页 > 解决方案 > dnorm() 如何在 sapply 循环中处理分位数向量

问题描述

我正在研究Richard McElreath 的Statistical Rethinking,并且对他在第 84 页使用的一些代码的工作方式感到困惑。该代码使用贝叶斯网格近似来推导两个模型参数,musigma估计样本中的高度分布。

这是代码

首先,我们制作一个候选mu值列表

mu.list <- seq(from = 140, to = 160, length.out = 200) 

然后是候选sigma值列表

sigma.list <- seq(from = 4, to = 9, length.out = 200) # grid of candidate sigma values

mu然后我们用和的所有可能组合制作一个数据框sigma

post <- expand.grid(mu = mu.list, sigma = sigma.list) # expand grid so every mu is matched with every sigma

这是一个有 40000 行的数据集。

nrow(post)

[1] 40000

现在假设我们有一个测量高度的样本,其中包含 5 个测量值。

heights <- c(151.76, 139.70, 136.52, 156.84, 145.41)

现在对于我不理解的部分,一个合理的复杂循环,根据五个高度测量的样本计算和sapply的 40000 个候选组合中的每一个的对数似然。musigma

postVec <- sapply(1:nrow(post), function (i) sum( dnorm( 
      heights, # vector of heights
      mean = post$mu[i], # candidate mean height value from corresponding position in grid
      sd = post$sigma[i], # candidate sigma value from corresponding position in the grid
      log = TRUE) ) # make values logs
)

我们从中得到的是循环是一个长 40000 个值的向量,数据帧的每一行都有一个值post

length(postVec)

[1] 40000

我不明白的是,如果我们dnorm()退出循环并为均值和 sd 使用单个值,但在第一个参数中传递相同的 5 值样本高度样本向量,就像这样

dnorm( heights, mean = 140, sd = 4, log = TRUE )

我们得到五个值

[1]  -6.627033  -2.308045  -2.683683 -11.167283  -3.219861

所以我的问题是:为什么 sapply 循环传递到 postVec 上面的向量中会产生 40000 个值,而不是 5 x 40000 = 200000 个值?

为什么dnorm()函数在循环外返回五个值,sapply()但(似乎)在循环内只返回一个值?

标签: r

解决方案


sum之前错过了dnorm:在 40000 个案例中的每一个案例中,它将这 5 个值相加,以计算整体的对数似然,heights而不仅仅是单个观察。

例如,如果没有sum两个组合,我们确实有

sapply(1:2, function (i) dnorm( 
  heights,
  mean = post$mu[i],
  sd = post$sigma[i],
  log = TRUE)
)
#            [,1]       [,2]
# [1,]  -6.627033  -6.553479
# [2,]  -2.308045  -2.310245
# [3,]  -2.683683  -2.705858
# [4,] -11.167283 -11.061820
# [5,]  -3.219861  -3.186194

sum我们有上述矩阵的列和:

sapply(1:2, function (i) sum(dnorm( 
  heights,
  mean = post$mu[i],
  sd = post$sigma[i],
  log = TRUE)
))
# [1] -26.00591 -25.81760

推荐阅读