Skip to content

Instantly share code, notes, and snippets.

@bwiernik
Last active January 27, 2020 22:02
Show Gist options
  • Save bwiernik/bd8cc7b55e5d583396ef886f4fe0bee6 to your computer and use it in GitHub Desktop.
Save bwiernik/bd8cc7b55e5d583396ef886f4fe0bee6 to your computer and use it in GitHub Desktop.
Function to compute simple linear regression coefficients and their covariances
#####
# Function: coef_cov
# Author: Brenton M. Wiernik
# Date: 2020-01-27
# Version: 1.0
#
# Computes univariate linear regresssion models,
# predicting each response variable [`.y`] with each
# predictor variable [`.x`]. Returns the coefficients
# and their variance-covariance matrix.
#
# Arguments:
# .data A data frame containing variables to estimate models.
# .y The column names or indices in .data for the response variables.
# .x The column names or indices in .data for the predictor variables.
#
# Returns:
# A list containing the estimated coefficients (`coef`) and their
# variance-covariance matrix (`vcov`)
#
# Note: Missing values in `.data` will be dropped listwise.
#
#####
coef_cov <- function(.data, .y, .x) {
if (is.null(colnames(.data))) stop(".data must have names")
if (is.numeric(.y)) y <- colnames(.data[,.y]) else y <- .y
if (is.numeric(.x)) x <- colnames(.data[,.x]) else x <- .x
dat <- na.omit(.data[,c(y, x)])
m <- sapply(x, function(.) lm(as.matrix(dat[,y]) ~ dat[,.]), simplify = FALSE)
COEF <- as.vector(sapply(m, function(.) coef(.)[seq(2, 2*length(y), by = 2)]))
names(COEF) <- as.vector(outer(y, x, "paste", sep="_"))
vcs <- sapply(m, function(.) vcov(.)[seq(2, 2*length(y), by = 2), seq(2, 2*length(y), by = 2)], simplify = FALSE)
eps <- sapply(m, resid, simplify = FALSE)
VC <- as.matrix(Matrix::bdiag(vcs))
rownames(VC) <- colnames(VC) <- as.vector(outer(y, x, "paste", sep="_"))
VC[upper.tri(VC)] <- 0
for (r in seq(1, nrow(VC), length(y))[-1]) {
rs <- r:(r + length(y) - 1)
r_x <- which(r == seq(1, nrow(VC), length(y)))
for (c in seq(1, ncol(VC), length(y))[-length(x)]) {
cs <- c:(c + length(y) - 1)
c_x <- which(c == seq(1, nrow(VC), length(y)))
xr <- dat[,x[r_x]]
xc <- dat[,x[c_x]]
VC[rs, cs] <- solve(t(xr) %*% xr) %*% t(xr) %*% eps[[r_x]] %*% t(eps[[c_x]]) %*% xc %*% solve(t(xc) %*% xc)
}
}
VC <- VC + t(VC) - diag(diag(VC))
return(list(coef = COEF, vcov = VC))
}
coef_cov(psych::bfi, 1:5, 6:11)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment