Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Although this blog’s primary focus is time series, one feature I missed from Stata was the simple marginal effects command, ‘mfx compute’, for cross-sectional work, and I could not find an adequate replacement in R. To bridge this gap, I’ve written a (rather messy) R function to produce marginal effects readout for logit and probit models.
If we want to analyse the effect of a change in some explanatory variable, say
where
the standard normal cumulative distribution function. Taking the derivative of either model with respect to the jth explanatory variable is a simple application of the chain rule; for the probit model:
For example, using a dataset provided by Jeff Wooldridge, MROZ.dta, we can compare results from Stata and R.
R code:
require(foreign) # a<-read.dta("MROZ.dta",convert.factors = F) # logit1 <- glm(inlf ~ nwifeinc + educ + exper + expersq + age + kidslt6 + kidsge6, family=binomial(link="logit"), data=a) probit1 <- glm(inlf ~ nwifeinc + educ + exper + expersq + age + kidslt6 + kidsge6, family=binomial(link="probit"), data=a) # mfx(logit1) mfx(probit1) #
Stata code and output:
R output:
‘mfx’ function:
mfx<-function(x){ bb<-data.frame(x$coefficients) bb2<-data.frame(mean(x$data,na.rm=T)) bbh<-as.character(rownames(bb)) bbmeans<-bb2[bbh[2:nrow(bb)],] jkj <-bb[2:nrow(bb),]*bbmeans # M3<-sum(jkj) + bb[1,] # if (ll<-x$family$link=="probit"){ probitmfx <- data.frame(mfx=dnorm(M3)*bb[2:nrow(bb),],row.names=bbh[2:nrow(bb)]) } else{probitmfx <- data.frame(mfx=dlogis(M3)*bb[2:nrow(bb),],row.names=bbh[2:nrow(bb)])} # bbse<-bb/summary(x)$coef[,2] mfxse<-probitmfx/bbse[2:nrow(bb),] # probitmfxfull <- data.frame(mfx=probitmfx,SE=mfxse,bbmeans,summary(x)$coef[2:nrow(bb),3],summary(x)$coef[2:nrow(bb),4],row.names=bbh[2:nrow(bb)]) colnames(probitmfxfull) <- c("mfx","SE","Mean Value","z","Pr(>|z|)") # logl <- 0.5*(-x$aic + 2*nrow(bb)) #McFadden's R2 depen <- x$data[,1] depenglm <- glm(depen ~ 1, family=binomial(link=x$family$link),data=x$data) logldepen <- 0.5*(-depenglm$aic + 2) psr2<- 1 - (logl/logldepen) # obs<-nrow(x$data) #SBC/BIC sbc<- -2*logl + log(obs)*nrow(bb) #HQIC HIC<- -2*logl + 2*log(log(obs))*nrow(bb) #Logit? if (qq<-x$family$link=="logit"){ } else{} #CDF of Mean Model if (ll == TRUE){ BigProb<-pnorm(M3) } else {BigProb<-plogis(M3)} #LR Test LRTest<- -2*(logl - logldepen) dfLR<-nrow(bb) - 1 LRp<-dchisq(LRTest,df=dfLR) LRdata <- data.frame(LRTest, dfLR,LRp) colnames(LRdata) <- c("Test Statistic","DF","P-Value") rownames(LRdata) <- "LR Test" # tests<-rbind(BigProb,logl,psr2,x$aic,HIC,sbc) tests<-data.frame(tests) colnames(tests)<-"" rownames(tests)<-c("CDF(Evaluated at the Mean):","Log-Likelihood:","McFadden's R2:","Akaike Information Criterion:","Hannan-Quinn Criterion:","Schwarz's Bayesian Criterion:") # cat("MFX Function for Logit and Probit", "\n") cat("", "\n") if (qq<-x$family$link=="logit"){ cat("This is a Logit Model","\n") } else if (qq<-x$family$link=="probit"){ cat("This is a Probit Model","\n") } else {cat("","\n")} cat("", "\n") cat("Reporting Marginal Effects, Evaluated at the Mean", "\n") cat("", "\n") printCoefmat(probitmfxfull, P.value=TRUE, has.Pvalue=TRUE) cat("", "\n") cat("Observations:", obs, "\n") cat("", "\n") printCoefmat(tests, P.value=F, has.Pvalue=F) cat("", "\n") cat("Likelihood-Ratio Test:", "\n") printCoefmat(LRdata, P.value=T, has.Pvalue=T) cat("", "\n") }
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.