Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programming a Bivariate Normal CDF in R

Tags:

r

statistics

I have a question regarding coding a function that contains a bivariate normal CDF in R. The function I am trying to code requires one bivariate normal CDF, that should be calculated differently depending on the observation. Specifically, depending upon the value of a certain variable, the correlation should "switch" between being positive and negative, but there should be no difference in the call.

This style of function has been coded in LIMDEP and I am trying to replicate it, but have not been able to get it to work in R. The command in LIMDEP to calculate a bivariate normal CDF is "BVN(x1, x2, r)", which explicitly requires the two variables used for calculation (x1, x2) and the correlation (r). LIMDEP uses the Gauss-Laguerre 15 point quadrature to calculate the bivariate normal CDF.

In R, it appears that two packages calculate the multivariate normal CDF. I have been trying the mnormt package (though there is the mvtnorm package as well--I do not see a major difference) that uses the Genz method, which seems to be similar, but more general than the Gauss-Laguerre 15 quadrature method used in LIMDEP (referencing the papers under ?pmnorm).

Everytime that I have tried to use the mnormt package, the command pmnorm(), requires the form: pmnorm(data, mean, varcov), which I have not been able to code for correlation switching.

Any ideas how to get this to work??

Here is an example of some trivial code to explain what I am talking about what I would like to do (except inside of a function without the for loop):

 library(mnormt)
 A <- c(0,1, 1, 1, 0, 1, 0, 1, 0, 1)
 q <- 2*A-1 
 set.seed(1234)
 x <- rnorm(10)
 y <- rnorm(10, 2, 2)

 #Need to return a value of the CDF for each row of data:
 cdf.results <- 0
 for(i in 1:length(A)){
 vc.mat <- matrix(c(1, q[i]*.7, q[i]*.7, 1.3), 2, 2)
 cdf.results[i] <- pmnorm(cbind(x[i], y[i]), c(0, 0), vc.mat) 
 }
 cdf.results

Thanks for your help!

like image 443
Tony Avatar asked Jun 03 '11 17:06

Tony


People also ask

How do you create a bivariate normal?

Two random variables X and Y are said to be bivariate normal, or jointly normal, if aX+bY has a normal distribution for all a,b∈R. In the above definition, if we let a=b=0, then aX+bY=0. We agree that the constant zero is a normal random variable with mean and variance 0.

How do you sample a bivariate distribution?

Hence, a sample from a bivariate Normal distribution can be simulated by first simulating a point from the marginal distribution of one of the random variables and then simulating from the second random variable conditioned on the first.


1 Answers

It sounds like all you need is 1) to make your script into a function so it can apply to arbitrary x,y and q and 2) to get rid of the for loop. If that is the case ?function and ?apply should give you what you need.

BVN=function(x,y,q) {

  cdf.results=apply(cbind(x,y,q),1,FUN=function(X) 
       {
      x=X[1]
      y=X[2]
      q=X[3]
          vc.mat <- matrix(c(1, q*.7, q*.7, 1.3), 2, 2)
          pmnorm(cbind(x, y), c(0, 0), vc.mat)     
                    # I think you may want c(0,2) but not sure
        }
                   )
 cdf.results
}



BVN(x,y,q)

Here x,y and q are how you wrote above. Maybe you want the function to take matrix r, like in limdep? It wouldn't be much different.

like image 140
Seth Avatar answered Sep 28 '22 01:09

Seth