[R] mixture normal distributions
Martin Maechler
maechler at stat.math.ethz.ch
Fri Feb 10 23:16:10 CET 2006
>>>>> "Martin" == Martin Maechler <maechler at stat.math.ethz.ch>
>>>>> on Fri, 10 Feb 2006 22:20:11 +0100 writes:
>>> Dear R helper, I mange to transform uniform sequences to
>>> mixture normal distributions using the following cods:
Martin> you forgot to mention the important fact that you
Martin> are working with package "nor1mix" (of which I am
Martin> the maintainer which you could have seen from
Martin> library(help = nor1mix) or
Martin> packageDescription("nor1mix")
>>> > K<-50000 > prime<-c(29) , where 29 is prim number >
>>> UN<-seq(1:K)%*%t(sqrt(prime)) > U1<-UN-as.integer(UN) >
>>> e<-norMix(mu=c(-0.825,0.275), sig2 = c(0.773,0.773), w =
>>> c(0.25,0.75), name = NULL, long.name = FALSE) >
>>> U<-matrix(qnorMix(e,U1),K,1),
Martin> This looks like you want to generate pseudo-random
Martin> values from the mixture distribution.
Martin> However by the slowest most possible way: qnorMix()
Martin> is really slow because it calls uniroot() for each
Martin> value.
Martin> rnorMix() will generate random values distributed
Martin> according to the normal mixture very very
Martin> efficiently (particularly compared to using
Martin> qnorMix()).
Martin> But indeed, you have detected a bug in qnorMix()
Martin> (that happens pretty rarely). Indeed your example
Martin> also shows that the algorithm can be much improved
Martin> in some cases.
Martin> The next verion of nor1mix should contain a more
Martin> "robust" qnorMix() function.
in the mean time, you can use the following which already fixes
the problem you found :
qnorMix <- function(obj, p)
{
if (!is.norMix(obj))
stop("'obj' must be a 'Normal Mixture' object!")
mu <- obj[, "mu"]
sd <- sqrt(obj[, "sig2"])
k <- nrow(obj)# = #{components}
if(k == 1) # one component
return(qnorm(p, mu, sd))
## else
## vectorize in `p' :
r <- p
left <- p <= 0 ; r[left] <- -Inf
right <- p >= 1 ; r[right] <- Inf
imid <- which(mid <- !left & !right) # 0 < p < 1
## p[] increasing for easier root finding start:
p <- sort(p[mid], index.return = TRUE)
ip <- imid[p$ix]
pp <- p$x
for(i in seq(along=pp)) {
rq <- range(qnorm(pp[i], mu, sd))
## since pp[] is increasing, we can start from last 'root':
if(i > 1) rq[1] <- root
## make sure, 'lower' is such that f(lower) < 0 :
delta.r <- 0.01*abs(rq[1])
ff <- function(l) pnorMix(obj,l) - pp[i]
while(ff(rq[1]) > 0) rq[1] <- rq[1] - delta.r
root <- uniroot(ff, interval = rq)$root
r[ip[i]] <- root
}
r
}
I hope this helps you.
>>> But somtimes if i use ,e.g, 23 or 11 instead of 29 it
>>> will give me the following error.
>>>
>>> > K<-30000 > prime<-c(23) >
>>> UN<-seq(1:K)%*%t(sqrt(prime)) > U1<-UN-as.integer(UN) >
>>> e<-norMix(mu=c(-0.825,0.275), sig2 = c(0.773,0.773), w =
>>> c(0.25,0.75), name = NULL, long.name = FALSE) >
>>> U<-matrix(qnorMix(e,U1),K,1) Error in
>>> uniroot(function(l) pnorMix(obj, l) - pp[i], interval =
>>> rq) : f() values at end points not of opposite sign
>>>
>>>
>>> I am seeking help how to avoid this error.
>>>
>>> Many thanks for your help in advance.
>>>
>>> My E-mail is aleid2001 at yahoo.com
>>>
>>> Al-Eid
>>>
>>> The university of Manchester.
Martin> ______________________________________________
Martin> R-help at stat.math.ethz.ch mailing list
Martin> https://stat.ethz.ch/mailman/listinfo/r-help PLEASE
Martin> do read the posting guide!
Martin> http://www.R-project.org/posting-guide.html
More information about the R-help
mailing list