[R] truncated normal

Duncan Murdoch murdoch at stats.uwo.ca
Thu Jul 24 02:48:59 CEST 2008

On 23/07/2008 8:17 PM, cindy Guo wrote:
> Yes, I know. I mean if I want to generate 100 numbers from
> N(0,1)I((0,1),(5,10)). There are two intervals (0,1) and (5,10). Then the
> function will give 50 numbers in the first interval and 50 in the other.

No, it doesn't handle that case at all.  I didn't realize that's what 
you wanted.  Sorry.

I've posted this back to the mailing list; maybe someone else will help 
you.  (This is one reason it's not a good idea to take discussions 
offline:  someone else might have recognized my misunderstanding earlier.)

Duncan Murdoch

> Cindy
> On 7/23/08, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
>> cindy Guo wrote:
>>> Dear Dr. Murdoch,
>>>  First thank you very much for your reply. But it seems to me that it will
>>> generate a point with equal probability in the two intervals. I mean if I
>>> generage 100 points, then 50 will be in one interval and the other 50 in the
>>> other interval. I think more points should be in the interval closer to the
>>> mean. What do you think?
>> I think you mean something different from me when you say a "truncated"
>> distribution.  My function would generate 100 points in whatever intervals
>> you specified.
>> Duncan Murdoch
>>>  Thanks a lot,
>>>  Cindy
>>>  On 7/23/08, *Duncan Murdoch* <murdoch at stats.uwo.ca <mailto:
>>> murdoch at stats.uwo.ca>> wrote:
>>>    On 7/23/2008 4:22 PM, Duncan Murdoch wrote:
>>>        On 7/23/2008 3:41 PM, cindy Guo wrote:
>>>            Hi, I want to generate random samples from truncated
>>>            normal say
>>>            Normal(0,1)Indicator((0,1),(2,4)). It has more than one
>>>            intervals. In the
>>>            library msm, it seems to me that the 'lower' and 'upper'
>>>            arguments can only
>>>            be a number. I tried rtnorm(1,mean=0,sd=1,
>>>            lower=c(0,2),upper=c(1,4)) and it
>>>            didn't work. Can you tell me  how I can do truncated
>>>            normal at more than one
>>>            intervals?
>>>        The inverse CDF method will work.  For example, this untested
>>>        code:
>>>        rtruncnorm <- function(n, mean=0, sd=1, lower=-Inf, upper=Inf) {
>>>          plower <- pnorm(lower, mean, sd) # get the probability
>>>        values for the
>>>                                           # lower limits
>>>          pupper <- pnorm(upper, mean, sd) # ditto for the upper limits
>>>          p <- plower + (pupper - plower)*runif(n) # get random values
>>>        between
>>>                                                   # those
>>>          qnorm(p, mean, sd)  # invert the CDFs
>>>        }
>>>        As I said, this is untested, but it should work if all of
>>>        mean, sd, lower, and upper are the same length, and in some
>>>        cases where they aren't.
>>>        Duncan Murdoch
>>>    One case where the code above will *not* work is if your
>>>    truncation is too far out in the tails, e.g. a standard normal,
>>>    truncated to be in the interval [100, 101].  It is possible to do
>>>    those in R, but it's tricky to avoid rounding error:  in the
>>>    example above, both plower and pupper will be exactly 1 in this
>>>    case.  You need to do calculations on a log scale, and work with
>>>    upper tails instead of lower ones.  It all gets kind of messy.
>>>    Duncan Murdoch

More information about the R-help mailing list