Last active
August 4, 2026 15:34
-
-
Save utkuturk/53a6b3c59cecbd3be5875086aa931d16 to your computer and use it in GitHub Desktop.
i want both tables and the coefficient whisker plots, but i dont like how many things just cuts through the text. i wrote an automated code that makes nice tables with whisker plots with tikz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fmt_num <- function(x, digits = 2) { | |
| s <- sprintf(paste0("%.", digits, "f"), abs(x)) | |
| ifelse(x < 0, paste0("$-$", s), paste0("\\pz", s)) | |
| } | |
| fmt_ci <- function(lo, hi, digits = 2) { | |
| paste0("[", fmt_num(lo, digits), "~, ", fmt_num(hi, digits), "]") | |
| } | |
| fmt_p <- function(p, digits = 2) { | |
| if (p > 0.99) { | |
| return("$>0.99$") | |
| } | |
| if (p < 0.01) { | |
| return("$<0.01$") | |
| } | |
| paste0("$\\pr ", sprintf(paste0("%.", digits, "f"), p), "$") | |
| } | |
| dw_cell <- function(lo, mid, hi, digits = 2) { | |
| r <- function(x) sprintf(paste0("%.", digits, "f"), x) | |
| paste0("\\dw{", r(lo), "}{", r(mid), "}{", r(hi), "}") | |
| } | |
| dw_row <- function(label, mid, lo, hi, p, digits = 2) { | |
| paste( | |
| label, | |
| fmt_num(mid, digits), | |
| fmt_ci(lo, hi, digits), | |
| fmt_p(p), | |
| dw_cell(lo, mid, hi, digits), | |
| sep = " & " | |
| ) | |
| } | |
| library(brms) | |
| dw_table <- function(fit, labels = NULL, digits = 2) { | |
| draws <- as.matrix(fit) | |
| bs <- grep("^b_", colnames(draws), value = TRUE) | |
| bs <- setdiff(bs, "b_Intercept") | |
| mid <- colMeans(draws[, bs, drop = FALSE]) | |
| lo <- apply(draws[, bs, drop = FALSE], 2, quantile, 0.025) | |
| hi <- apply(draws[, bs, drop = FALSE], 2, quantile, 0.975) | |
| p <- colMeans(draws[, bs, drop = FALSE] > 0) | |
| if (is.null(labels)) { | |
| labels <- sub("^b_", "", bs) | |
| } | |
| # scale limits: round outward to the nearest 0.5, keep 0 inside | |
| dwmin <- min(floor(min(lo, 0) * 2) / 2, -0.5) | |
| dwmax <- max(ceiling(max(hi, 0) * 2) / 2, 0.5) | |
| rows <- mapply( | |
| dw_row, | |
| labels, | |
| mid, | |
| lo, | |
| hi, | |
| p, | |
| MoreArgs = list(digits = digits) | |
| ) | |
| c( | |
| paste0("\\renewcommand{\\dwmin}{", dwmin, "}"), | |
| paste0("\\renewcommand{\\dwmax}{", dwmax, "}"), | |
| "\\begin{tabular}{lccc c}", | |
| " \\toprule", | |
| " Effect & $\\beta$ & 95\\% CrI & P($\\beta > 0$) & \\dwaxis\\\\", | |
| " \\midrule", | |
| paste0(" ", rows, " \\\\"), | |
| " \\bottomrule", | |
| "\\end{tabular}" | |
| ) | |
| } | |
| # how to use: | |
| # fit <- brm( | |
| # response ~ gram * | |
| # att_num + | |
| # (1 + gram * att_num | subject) + | |
| # (1 + gram * att_num | item), | |
| # family = bernoulli("logit"), | |
| # data = d | |
| # ) | |
| # writeLines( | |
| # dw_table( | |
| # fit, | |
| # labels = c("Grammaticality (G)", "Attractor Number (A)", "G $\\times$ A") | |
| # ), | |
| # "exp1-coef-table.tex" | |
| # ) | |
| # Do not forget to end the following to your latex preamble and uncomment it. | |
| # \usepackage{tikz} | |
| # % ---- inline dot-and-whisker on a shared scale ---------------------- | |
| # \newcommand{\dwmin}{-3.5} % left edge of scale | |
| # \newcommand{\dwmax}{7.8} % right edge of scale | |
| # \newlength{\dwwidth}\setlength{\dwwidth}{26mm} % column width | |
| # \newlength{\dwheight}\setlength{\dwheight}{2.6mm}% whisker cap height | |
| # % \dw{lower}{estimate}{upper} | |
| # \newcommand{\dw}[3]{% | |
| # \pgfmathsetmacro{\dwlo}{(#1-(\dwmin))/((\dwmax)-(\dwmin))}% | |
| # \pgfmathsetmacro{\dwmd}{(#2-(\dwmin))/((\dwmax)-(\dwmin))}% | |
| # \pgfmathsetmacro{\dwhi}{(#3-(\dwmin))/((\dwmax)-(\dwmin))}% | |
| # \pgfmathsetmacro{\dwzero}{(0-(\dwmin))/((\dwmax)-(\dwmin))}% | |
| # \begin{tikzpicture}[baseline=-0.55ex, x=\dwwidth, y=\dwheight] | |
| # \draw[gray!25, line width=0.4pt] (0,0) -- (1,0); | |
| # \draw[gray!70, densely dashed, line width=0.4pt] | |
| # (\dwzero,-0.55) -- (\dwzero,0.55); | |
| # \draw[line width=0.7pt] (\dwlo,0) -- (\dwhi,0); | |
| # \draw[line width=0.5pt] (\dwlo,-0.4) -- (\dwlo,0.4); | |
| # \draw[line width=0.5pt] (\dwhi,-0.4) -- (\dwhi,0.4); | |
| # \node[circle, fill, inner sep=1.1pt] at (\dwmd,0) {}; | |
| # \end{tikzpicture}% | |
| # } | |
| # \newcommand{\dwaxis}{% | |
| # \begin{tikzpicture}[baseline=-0.55ex, x=\dwwidth, y=\dwheight] | |
| # \pgfmathsetmacro{\dwzero}{(0-(\dwmin))/((\dwmax)-(\dwmin))} | |
| # \draw[gray!50] (0,0) -- (1,0); | |
| # \foreach \v in {-3,0,3,6}{% | |
| # \pgfmathsetmacro{\p}{(\v-(\dwmin))/((\dwmax)-(\dwmin))} | |
| # \ifdim\p pt<0pt\else\ifdim\p pt>1pt\else | |
| # \draw[gray!50] (\p,0) -- (\p,0.5); | |
| # \node[font=\tiny, above=-1pt] at (\p,0.4) {\v}; | |
| # \fi\fi} | |
| # \end{tikzpicture}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment