7

我有一个从我的原始数据中获得的 100 万条记录的样本。(供您参考,您可以使用可能产生近似相似分布的虚拟数据

b <- data.frame(matrix(rnorm(2000000, mean=c(8,17), sd=2)))
c <- b[sample(nrow(b), 1000000), ]

) 我认为直方图是两个对数正态分布的混合,我尝试使用以下代码使用 EM 算法拟合求和分布:

install.packages("mixtools")
lib(mixtools)
#line below returns EM output of type mixEM[] for mixture of normal distributions
c1 <- normalmixEM(c, lambda=NULL, mu=NULL, sigma=NULL) 
plot(c1, density=TRUE)

第一个图是对数似然图,第二个图(如果再次点击返回)给出类似于以下密度曲线:

混合模型密度曲线

正如我提到的,c1 是 mixEM[] 类型,而 plot() 函数可以适应这种情况。我想用颜色填充密度曲线。使用 ggplot2() 很容易做到这一点,但 ggplot2() 不支持 mixEM[] 类型的数据并抛出此消息:

ggplot 不知道如何处理 mixEM 类的数据

有没有其他方法可以解决这个问题?

4

2 回答 2

9

查看返回对象的结构(这应该记录在帮助中):

> # simple mixture of normals:
> x=c(rnorm(10000,8,2),rnorm(10000,17,4))
> xMix = normalmixEM(x, lambda=NULL, mu=NULL, sigma=NULL)

怎么办:

> str(xMix)
List of 9
 $ x         : num [1:20000] 6.18 9.92 9.07 8.84 9.93 ...
 $ lambda    : num [1:2] 0.502 0.498
 $ mu        : num [1:2] 7.99 17.05
 $ sigma     : num [1:2] 2.03 4.02
 $ loglik    : num -59877

lambda、mu 和 sigma 分量定义返回的法线密度。qplot您可以使用和在 ggplot 中绘制这些图stat_function。但首先创建一个返回缩放法线密度的函数:

sdnorm =
function(x, mean=0, sd=1, lambda=1){lambda*dnorm(x, mean=mean, sd=sd)}

然后:

qplot(x,geom="density") + stat_function(fun=sdnorm,args=list(mean=xMix$mu[1],sd=xMix$sigma[1], lambda=xMix$lambda[1]),fill="blue",geom="polygon")  + stat_function(fun=sdnorm,args=list(mean=xMix$mu[2],sd=xMix$sigma[2], lambda=xMix$lambda[2]),fill="#FF0000",geom="polygon") 

在此处输入图像描述

或者ggplot你有什么技能。密度上的透明颜色可能很好。

ggplot(data.frame(x=x)) + 
 geom_histogram(aes(x=x,y=..density..),fill="white",color="black") +
 stat_function(fun=sdnorm,
    args=list(mean=xMix$mu[2],
             sd=xMix$sigma[2],
             lambda=xMix$lambda[2]),
             fill="#FF000080",geom="polygon") +
 stat_function(fun=sdnorm,
    args=list(mean=xMix$mu[1],
             sd=xMix$sigma[1],
             lambda=xMix$lambda[1]),
             fill="#00FF0080",geom="polygon")

生产:

在此处输入图像描述

于 2014-08-14T17:31:52.423 回答
5

这是一种稍微不同的方法,它使用geom_ploygon(...)而不是多次调用stat_function(...). 一个问题stat_function(...)是使用参数传递的辅助参数(本示例中的 mu、sigma 和 lambda)args=list(...)不能包含在美学映射中,因此您必须stat_function(...)像 @Spacedman 的解决方案一样多次调用.

这种方法在 ggplot 之外构建 PDF,并使用一次调用geom_polygon(...). 因此,对于混合物中的任意数量的分布,它无需修改即可工作。

# ggplot mixture plot
gg.mixEM <- function(EM) {
  require(ggplot2)
  x       <- with(EM,seq(min(x),max(x),len=1000))
  pars    <- with(EM,data.frame(comp=colnames(posterior), mu, sigma,lambda))
  em.df   <- data.frame(x=rep(x,each=nrow(pars)),pars)
  em.df$y <- with(em.df,lambda*dnorm(x,mean=mu,sd=sigma))
  ggplot(data.frame(x=EM$x),aes(x,y=..density..)) + 
    geom_histogram(fill=NA,color="black")+
    geom_polygon(data=em.df,aes(x,y,fill=comp),color="grey50", alpha=0.5)+
    scale_fill_discrete("Component\nMeans",labels=format(em.df$mu,digits=3))+
    theme_bw()
}

library(mixtools)
# two components
set.seed(1)    # for reproducible example
b <- rnorm(2000000, mean=c(8,17), sd=2)
c <- b[sample(length(b), 1000000) ]
c2 <- normalmixEM(c, lambda=NULL, mu=NULL, sigma=NULL) 
gg.mixEM(c2)

# three components
set.seed(1)
b <- rnorm(2000000, mean=c(8,17,30), sd=c(2,3,5))
c <- b[sample(length(b), 1000000) ]
library(mixtools)
c3 <- normalmixEM(c, k=3, lambda=NULL, mu=NULL, sigma=NULL) 
gg.mixEM(c3)

于 2014-08-14T18:43:27.207 回答