我正在尝试复制this论文中概述的空气质量数据的异常值检测方法,但要使用我自己的数据(颗粒物(PM)代替NO2)。我将使用R中的mtcars
数据集来说明我的问题。
我已经计算出每组中每个观测值的平方根变换数据的均值和标准偏差,每次均不包括当前观测值。例如,如果组具有值(1、3、7、5),则第一行的平均值和标准差将仅使用值(3、7、5)。以R索引而言,数据为group[-i]
。
data(mtcars)
mtcars$mpg_sqrt <- sqrt(mtcars[, c("mpg")] + (1 - min(mtcars$mpg)))
This和this示例提供了有关使用dplyr的均值和标准差如何实现这种类型的计算的示例。我已将此代码改编为mtcars
数据集,我的组是cyl
,值是mpg_sqrt
:
library(dplyr)
# Mean using dlpyr
mtcars <- as.data.frame(mtcars %>% group_by(cyl) %>%
mutate(mean_ = (sum(mpg) - mpg)/(n()-1)))
# Std. dev. using dplyr
mtcars <- as.data.frame(mtcars %>% group_by(cyl) %>%
mutate(stdev_ = sqrt(( sum((mpg - mean_)^2) - ((mpg - mean_)^2) ) / (n()-2))))
本文详细介绍,这些均值和标准差值不适用于基本正态分布。因此,为了估计这些基础值,我们使用最大似然估计(MLE)。因为每一行的数据都在变化,所以我每次都需要将新数据传递给对数似然函数,因此无法使用mle()
函数。 This先前的答案对此进行了解释。相反,我选择使用optim()
函数,我相信mle()
函数使用了内部函数。我的起始参数是截短分布的均值和标准差,函数是下面详述的对数似然函数(LL),要传递给LL函数的数据是没有当前观察值的组数据:
optim(par = c(mean_, stdev_), fn = LL, data = some_group_data[-i])
我试图实现这一点,但是我得到的值太高了,例如第3行的mean_ul = 2.083075e+55, stdev_ul = 1.119087e+56
应该与mean_
和stdev_
相差不大。显然,我的代码出了点问题。我尝试的实现目前仅使用循环,效率不是很高。如果可能的话,我想使用dplyr。
# Log likelihood function
LL = function(data, par) {
mu = par[1]
sigma = par[2]
loglike = 0
for(obs in data){
loglike = loglike +
log(1/(sqrt(2*pi)*sigma) *
exp(-1/2 * (obs - mu)^2/(sigma^2)))
}
return(loglike)
}
for(i in 1:nrow(mtcars)) {
print(i)
# Get parameters for row
mu = mtcars$mean_[i]
sigma = mtcars$stdev_[i]
# Get group data and exclude current row
group = mtcars$cyl[i]
group_data = mtcars[-i,]
group_data = group_data[group_data$cyl == group, c("mpg_sqrt")]
# Run optim() function
result <- optim(par = c(mu, sigma), fn = LL, data = unlist(group_data))
mtcars$mean_ul[i] <- result$par[1]
mtcars$stdev_ul[i] <- result$par[2]
print(mtcars$mean_ul[i])
print(mtcars$stdev_ul[i])
}
如何为每个组中的每一行使用MLE估计这些均值和标准差值(mean_ul
和stdev_ul
,其中ul表示“基础”),但每次不包括当前行/观测值?
请让我澄清一下您是否不了解。谢谢。