Plotting the data and fitted model. See Chapter 11 in Regression and Other Stories.


Load packages

library("rprojroot")
root<-has_file(".ROS-Examples-root")$make_fix_file()
library("rstanarm")

Simple model with const term, one pre-treatment predictor, and treatment indicator

Fake data

N <- 100
x <- runif(N, 0, 1)
z <- sample(c(0, 1), N, replace=TRUE)
a <- 1
b <- 2
theta <- 5
sigma <- 2
y <- a + b*x + theta*z +  rnorm(N, 0, sigma)
fake <- data.frame(x=x, y=y, z=z)

Model

fit <- stan_glm(y ~ x + z, data=fake, refresh = 0)

Plot Predictor vs Outcome

par(mfrow=c(1,2), mar=c(3,3,2,2), mgp=c(1.7,.5,0), tck=-.01)
for (i in 0:1){
  plot(range(x), range(y), type="n", xlab="Pre-treatment predictor, x", ylab="Outcome, y", main=paste("z =", i), bty="l")
  points(x[z==i], y[z==i], pch=20+i)
  abline(coef(fit)["(Intercept)"] + coef(fit)["z"]*i, coef(fit)["x"])
}

More complicated model with multiple pre-treatment predictors.

Fake data

Creating the linear predictor from the fitted multiple regression model

N <- 100
K <- 10
X <- array(runif(N*K, 0, 1), c(N, K))
z <- sample(c(0, 1), N, replace=TRUE)
a <- 1
b <- 1:K
theta <- 10
sigma <- 5
y <- a + X %*% b + theta*z +  rnorm(N, 0, sigma)
fake <- data.frame(X=X, y=y, z=z)

Model

fit <- stan_glm(y ~ X + z, data=fake, refresh = 0)

Plot Predictor vs Outcome

y_hat <- predict(fit)
par(mfrow=c(1,2), mar=c(3,3,2,2), mgp=c(1.7,.5,0), tck=-.01)
par(mfrow=c(1,2), pty="s")
for (i in 0:1){
  plot(range(y_hat,y), range(y_hat,y), type="n", xlab=expression(paste("Linear predictor, ", hat(y))), ylab="Outcome, y", main=paste("z =", i), bty="l")
  points(y_hat[z==i], y[z==i], pch=20+i)
abline(0, 1)
}

Plot Predictor vs Residual

r <- y - y_hat
par(mfrow=c(1,2), mar=c(3,3,2,2), mgp=c(1.7,.5,0), tck=-.01)
par(mfrow=c(1,2))
for (i in 0:1){
  plot(range(y_hat), range(r), type="n", xlab=expression(paste("Linear predictor, ", hat(y))), ylab="Residual, r", main=paste("z =", i), bty="l")
  points(y_hat[z==i], r[z==i], pch=20+i)
  abline(0, 0)
}

LS0tCnRpdGxlOiAiUmVncmVzc2lvbiBhbmQgT3RoZXIgU3RvcmllczogUmVzaWR1YWxzIgphdXRob3I6ICJBbmRyZXcgR2VsbWFuLCBKZW5uaWZlciBIaWxsLCBBa2kgVmVodGFyaSIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHJlYWRhYmxlCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQpQbG90dGluZyB0aGUgZGF0YSBhbmQgZml0dGVkIG1vZGVsLiBTZWUgQ2hhcHRlciAxMSBpbiBSZWdyZXNzaW9uCmFuZCBPdGhlciBTdG9yaWVzLgoKLS0tLS0tLS0tLS0tLQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNvbW1lbnQ9TkEpCiMgc3dpdGNoIHRoaXMgdG8gVFJVRSB0byBzYXZlIGZpZ3VyZXMgaW4gc2VwYXJhdGUgZmlsZXMKc2F2ZWZpZ3MgPC0gRkFMU0UKYGBgCgojIyMjIExvYWQgcGFja2FnZXMKCmBgYHtyIH0KbGlicmFyeSgicnByb2pyb290IikKcm9vdDwtaGFzX2ZpbGUoIi5ST1MtRXhhbXBsZXMtcm9vdCIpJG1ha2VfZml4X2ZpbGUoKQpsaWJyYXJ5KCJyc3RhbmFybSIpCmBgYAoKIyMgU2ltcGxlIG1vZGVsIHdpdGggY29uc3QgdGVybSwgb25lIHByZS10cmVhdG1lbnQgcHJlZGljdG9yLCBhbmQgdHJlYXRtZW50IGluZGljYXRvcgoKIyMjIyBGYWtlIGRhdGEKCmBgYHtyIH0KTiA8LSAxMDAKeCA8LSBydW5pZihOLCAwLCAxKQp6IDwtIHNhbXBsZShjKDAsIDEpLCBOLCByZXBsYWNlPVRSVUUpCmEgPC0gMQpiIDwtIDIKdGhldGEgPC0gNQpzaWdtYSA8LSAyCnkgPC0gYSArIGIqeCArIHRoZXRhKnogKyAgcm5vcm0oTiwgMCwgc2lnbWEpCmZha2UgPC0gZGF0YS5mcmFtZSh4PXgsIHk9eSwgej16KQpgYGAKCiMjIyMgTW9kZWwKCmBgYHtyIH0KZml0IDwtIHN0YW5fZ2xtKHkgfiB4ICsgeiwgZGF0YT1mYWtlLCByZWZyZXNoID0gMCkKYGBgCgojIyMjIFBsb3QgUHJlZGljdG9yIHZzIE91dGNvbWUKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgcGRmKHJvb3QoIlJlc2lkdWFscy9maWdzIiwicmVzaWRfMGEucGRmIiksIGhlaWdodD0zLjUsIHdpZHRoPTkpCmBgYApgYGB7ciB9CnBhcihtZnJvdz1jKDEsMiksIG1hcj1jKDMsMywyLDIpLCBtZ3A9YygxLjcsLjUsMCksIHRjaz0tLjAxKQpmb3IgKGkgaW4gMDoxKXsKICBwbG90KHJhbmdlKHgpLCByYW5nZSh5KSwgdHlwZT0ibiIsIHhsYWI9IlByZS10cmVhdG1lbnQgcHJlZGljdG9yLCB4IiwgeWxhYj0iT3V0Y29tZSwgeSIsIG1haW49cGFzdGUoInogPSIsIGkpLCBidHk9ImwiKQogIHBvaW50cyh4W3o9PWldLCB5W3o9PWldLCBwY2g9MjAraSkKICBhYmxpbmUoY29lZihmaXQpWyIoSW50ZXJjZXB0KSJdICsgY29lZihmaXQpWyJ6Il0qaSwgY29lZihmaXQpWyJ4Il0pCn0KYGBgCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgZGV2Lm9mZigpCmBgYAoKIyMgTW9yZSBjb21wbGljYXRlZCBtb2RlbCB3aXRoIG11bHRpcGxlIHByZS10cmVhdG1lbnQgcHJlZGljdG9ycy4KCiMjIyMgRmFrZSBkYXRhCgpDcmVhdGluZyB0aGUgbGluZWFyIHByZWRpY3RvciBmcm9tIHRoZSBmaXR0ZWQgbXVsdGlwbGUgcmVncmVzc2lvbgptb2RlbAoKYGBge3IgfQpOIDwtIDEwMApLIDwtIDEwClggPC0gYXJyYXkocnVuaWYoTipLLCAwLCAxKSwgYyhOLCBLKSkKeiA8LSBzYW1wbGUoYygwLCAxKSwgTiwgcmVwbGFjZT1UUlVFKQphIDwtIDEKYiA8LSAxOksKdGhldGEgPC0gMTAKc2lnbWEgPC0gNQp5IDwtIGEgKyBYICUqJSBiICsgdGhldGEqeiArICBybm9ybShOLCAwLCBzaWdtYSkKZmFrZSA8LSBkYXRhLmZyYW1lKFg9WCwgeT15LCB6PXopCmBgYAoKIyMjIyBNb2RlbAoKYGBge3IgfQpmaXQgPC0gc3Rhbl9nbG0oeSB+IFggKyB6LCBkYXRhPWZha2UsIHJlZnJlc2ggPSAwKQpgYGAKCiMjIyMgUGxvdCBQcmVkaWN0b3IgdnMgT3V0Y29tZQoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBwZGYocm9vdCgiUmVzaWR1YWxzL2ZpZ3MiLCJyZXNpZF8wYi5wZGYiKSwgaGVpZ2h0PTQsIHdpZHRoPTkpCmBgYApgYGB7ciB9CnlfaGF0IDwtIHByZWRpY3QoZml0KQpwYXIobWZyb3c9YygxLDIpLCBtYXI9YygzLDMsMiwyKSwgbWdwPWMoMS43LC41LDApLCB0Y2s9LS4wMSkKcGFyKG1mcm93PWMoMSwyKSwgcHR5PSJzIikKZm9yIChpIGluIDA6MSl7CiAgcGxvdChyYW5nZSh5X2hhdCx5KSwgcmFuZ2UoeV9oYXQseSksIHR5cGU9Im4iLCB4bGFiPWV4cHJlc3Npb24ocGFzdGUoIkxpbmVhciBwcmVkaWN0b3IsICIsIGhhdCh5KSkpLCB5bGFiPSJPdXRjb21lLCB5IiwgbWFpbj1wYXN0ZSgieiA9IiwgaSksIGJ0eT0ibCIpCiAgcG9pbnRzKHlfaGF0W3o9PWldLCB5W3o9PWldLCBwY2g9MjAraSkKYWJsaW5lKDAsIDEpCn0KYGBgCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgZGV2Lm9mZigpCmBgYAoKIyMjIyBQbG90IFByZWRpY3RvciB2cyBSZXNpZHVhbAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBwZGYocm9vdCgiUmVzaWR1YWxzL2ZpZ3MiLCJyZXNpZF8wYy5wZGYiKSwgaGVpZ2h0PTMuNSwgd2lkdGg9OSkKYGBgCmBgYHtyIH0KciA8LSB5IC0geV9oYXQKcGFyKG1mcm93PWMoMSwyKSwgbWFyPWMoMywzLDIsMiksIG1ncD1jKDEuNywuNSwwKSwgdGNrPS0uMDEpCnBhcihtZnJvdz1jKDEsMikpCmZvciAoaSBpbiAwOjEpewogIHBsb3QocmFuZ2UoeV9oYXQpLCByYW5nZShyKSwgdHlwZT0ibiIsIHhsYWI9ZXhwcmVzc2lvbihwYXN0ZSgiTGluZWFyIHByZWRpY3RvciwgIiwgaGF0KHkpKSksIHlsYWI9IlJlc2lkdWFsLCByIiwgbWFpbj1wYXN0ZSgieiA9IiwgaSksIGJ0eT0ibCIpCiAgcG9pbnRzKHlfaGF0W3o9PWldLCByW3o9PWldLCBwY2g9MjAraSkKICBhYmxpbmUoMCwgMCkKfQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBkZXYub2ZmKCkKYGBgCgo=