2

From Stata:

margins, at(age=40)

To understand why that yields the desired result, let us tell you that if you were to type . margins margins would report the overall margin—the margin that holds nothing constant. Because our model is logistic, the average value of the predicted probabilities would be reported. The at() option fixes one or more covariates to the value(s) specified and can be used with both factor and continuous variables. Thus, if you typed

margins, at(age=40)

then margins would average over the data the responses for everybody, setting age=40.

Could someone help me which package could be useful? I tried already to find a mean of predicted values for the subset data, but it doesnt work for sequences, for example margins, at(age=40 (1)50).

jay.sf
  • 60,139
  • 8
  • 53
  • 110
Nata107
  • 41
  • 1
  • 3

1 Answers1

8

There are many ways to get marginal effects in R.

You should understand that Stata's margins, at are simply marginal effects evaluated at means or representative points (see this and the documentation).

I think that you'll like this solution best as it's most similar to what you're used to:

library(devtools)
install_github("leeper/margins")

Source: https://github.com/leeper/margins

margins is an effort to port Stata's (closed source) margins command to R as an S3 generic method for calculating the marginal effects (or "partial effects") of covariates included in model objects (like those of classes "lm" and "glm"). A plot method for the new "margins" class additionally ports the marginsplot command.

library(margins)
x <- lm(mpg ~ cyl * hp + wt, data = mtcars)
(m <- margins(x))
     cyl       hp       wt 
 0.03814 -0.04632 -3.11981

See also the prediction command (?prediction) in this package.

Asides from that, here are some other solutions I've compiled:

I. erer (package)

maBina() command

http://cran.r-project.org/web/packages/erer/erer.pdf

II. mfxboot

mfxboot <- function(modform,dist,data,boot=1000,digits=3){
  x <- glm(modform, family=binomial(link=dist),data)
  # get marginal effects
  pdf <- ifelse(dist=="probit",
                mean(dnorm(predict(x, type = "link"))),
                mean(dlogis(predict(x, type = "link"))))
  marginal.effects <- pdf*coef(x)
  # start bootstrap
  bootvals <- matrix(rep(NA,boot*length(coef(x))), nrow=boot)
  set.seed(1111)
  for(i in 1:boot){
    samp1 <- data[sample(1:dim(data)[1],replace=T,dim(data)[1]),]
    x1 <- glm(modform, family=binomial(link=dist),samp1)
    pdf1 <- ifelse(dist=="probit",
                   mean(dnorm(predict(x, type = "link"))),
                   mean(dlogis(predict(x, type = "link"))))
    bootvals[i,] <- pdf1*coef(x1)
  }
  res <- cbind(marginal.effects,apply(bootvals,2,sd),marginal.effects/apply(bootvals,2,sd))
  if(names(x$coefficients[1])=="(Intercept)"){
    res1 <- res[2:nrow(res),]
    res2 <- matrix(as.numeric(sprintf(paste("%.",paste(digits,"f",sep=""),sep=""),res1)),nrow=dim(res1)[1])
    rownames(res2) <- rownames(res1)
  } else {
    res2 <- matrix(as.numeric(sprintf(paste("%.",paste(digits,"f",sep=""),sep="")),nrow=dim(res)[1]))
    rownames(res2) <- rownames(res)
  }
  colnames(res2) <- c("marginal.effect","standard.error","z.ratio")
  return(res2)}

Source: http://www.r-bloggers.com/probitlogit-marginal-effects-in-r/

III. Source: R probit regression marginal effects

x1 = rbinom(100,1,.5)
x2 = rbinom(100,1,.3)
x3 = rbinom(100,1,.9)
ystar = -.5  + x1 + x2 - x3 + rnorm(100)
y = ifelse(ystar>0,1,0)
probit = glm(y~x1 + x2 + x3, family=binomial(link='probit'))
xbar <- as.matrix(mean(cbind(1,ttt[1:3])))

Now the graphic, i.e., the marginal effect of x1, x2 and x3

library(arm)
curve(invlogit(1.6*(probit$coef[1] + probit$coef[2]*x + probit$coef[3]*xbar[3] + probit$coef[4]*xbar[4]))) #x1
curve(invlogit(1.6*(probit$coef[1] + probit$coef[2]*xbar[2] + probit$coef[3]*x + probit$coef[4]*xbar[4]))) #x2
curve(invlogit(1.6*(probit$coef[1] + probit$coef[2]*xbar[2] + probit$coef[3]*xbar[3] + probit$coef[4]*x))) #x3

library(AER)
data(SwissLabor)
mfx1 <- mfxboot(participation ~ . + I(age^2),"probit",SwissLabor)
mfx2 <- mfxboot(participation ~ . + I(age^2),"logit",SwissLabor)
mfx3 <- mfxboot(participation ~ . + I(age^2),"probit",SwissLabor,boot=100,digits=4)

mfxdat <- data.frame(cbind(rownames(mfx1),mfx1))
mfxdat$me <- as.numeric(as.character(mfxdat$marginal.effect))
mfxdat$se <- as.numeric(as.character(mfxdat$standard.error))


# coefplot
library(ggplot2)
ggplot(mfxdat, aes(V1, marginal.effect,ymin = me - 2*se,ymax= me + 2*se)) +
  scale_x_discrete('Variable') +
  scale_y_continuous('Marginal Effect',limits=c(-0.5,1)) +
  theme_bw() +
  geom_errorbar(aes(x = V1, y = me),size=.3,width=.2) +
  geom_point(aes(x = V1, y = me)) +
  geom_hline(yintercept=0) +
  coord_flip() +
  opts(title="Marginal Effects with 95% Confidence Intervals")
Community
  • 1
  • 1
Hack-R
  • 22,422
  • 14
  • 75
  • 131
  • yea, but not marginal effects, but predictive margins, i.e. predictions when changing one x holding other things constant.... – Nata107 Aug 24 '16 at 19:04
  • @Nata107 When you know the partial ("marginal") effects you know how to calculate this. It gives you the equation to do so. You can set the values for predictions however you like and use one of the models above with a `predict` statement or calculate it directly. I'm not sure what related to this the `margins` command is giving you that the port of the `margins` command doesn't? Did you see the `prediction` command in that package? – Hack-R Aug 24 '16 at 19:07
  • it is like predict command, doesnt allow to use a subset or spesific value for x – Nata107 Aug 24 '16 at 19:25
  • for now I am using for (i in 5:17){ new<-subset(newdata, x1==i, select=c(x2,x3, xn)) print(mean(predict.lm(newreg1,new ))) } , but it is not very convenient – Nata107 Aug 24 '16 at 19:25
  • and for margins atmeans: xxdata <- data.frame(x1=c(5:17), x2=mean(newdata$x2), ...) kar<-predict.lm(newreg1,xxdata) – Nata107 Aug 24 '16 at 19:27
  • Just wondering if there are something "easier" and "user-friendly" – Nata107 Aug 24 '16 at 19:28
  • At III., I'm getting `Error in cbind(1, ttt[1:3]) : object 'ttt' not found`. – jay.sf Dec 30 '18 at 16:54
  • @jay.sf Hi, yes you will get that error if you just run the code snippets from the answer because the object was not created there. Please follow the link to see where it is created. – Hack-R Dec 30 '18 at 17:28
  • Thx, the linked question is not reproducible, though. Just wondered how to get eventually the plot with your code. – jay.sf Dec 30 '18 at 17:32