1

Based on the answers to this question (In R, plotting random effects from lmer (lme4 package) using qqmath or dotplot: how to make it look fancy?) I created "caterpillar plots" with qqmath from the lattice library. But I face the problem that I can't specify the title above the plots in a flexible way. I want to use bquote for formula expressions in the title like plot(x = 1, main = bquote(.("It works to write") ~ sigma [0]^2)).


Here is my example code:

require(lme4)  ## for lmer(), sleepstudy
require(lattice) ## for qqmath()

fit <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)

ranef_fit <- ranef(fit, condVar = TRUE)
qqmath(ranef_fit) #has title "Subject"

names(ranef_fit) <- "This works"
qqmath(ranef_fit) #now has title "This works"

names(ranef_fit) <- bquote(.("Doesn't work to write ") ~ sigma [0]^2) #doesn't work

This Website gives the hint, that I might want to use qqmath(x, main = attr(x, "title"). But for me it is unclear what x has to be: qqmath(ranef_fit, main = attr(x = qqmath(ranef_fit), "test title")) doesn't work.

Community
  • 1
  • 1
Qaswed
  • 3,649
  • 7
  • 27
  • 47
  • I don't think you understand what `bquote` is used for. Have you read the help page and tried the examples there? – Roland May 03 '16 at 13:47
  • @Roland you are correct, I don't understand the real purpose of `bquote` even if I read the help page and tried the examples. I use it as an alternative to `expression()`. Should I rename my question to "How to use expressions in qqmath?" Or am I lacking a fundamental unterstanding of expressions? Do you know a good and helpful site? But still: what do I have to do, that I can have greek letters in qqmath titles (like they can appear in "normal" plots)? Thank you. – Qaswed May 03 '16 at 14:09
  • I don't think this can be done with `qqmath`. It takes the titles from the names of `ranef_fit` and a name must be a character and can't be an expression. Possibly there might be a way using lattice functionality, but I would just change the code of `lme4:::qqmath.ranef.mer` to allow specifying names separately. – Roland May 03 '16 at 14:21
  • `qqmath` can handle `bquote`: `qqmath(rnorm(100), main = bquote(.("It works to write") ~ sigma [0]^2))`. I think the problem is, that `qqmath` is a generic function and `lme4:::qqmath.ranef.mer` only allows `main` to be `TRUE` or `FALSE`. – Qaswed May 03 '16 at 14:44
  • Yes. And that's still not an appropriate use of `bquote`, You should use `bquote` if you want to do this: `sometext <- "It works to write"; qqmath(rnorm(100), main = bquote(.(sometext) ~ sigma [0]^2))`. Otherwise, just use `expression("It works to write" ~ sigma [0]^2)`. – Roland May 03 '16 at 14:49

1 Answers1

1

After the hint of @Roland, I changed lme4:::qqmath.ranef.mer in such a way, that it allows flexible title. Basically I only had to change

mtit <- if (main) 
        nx

to

if(is.null(main)){
    mtit <- NULL
}else if(is.expression(main)){
    mtit <- main
}else if(main == TRUE){
    mtit <- nx
}else{
    mtit <- main
}

For reasons of completeness, here is the complete code with example:

require(lme4)  ## for lmer(), sleepstudy
require(lattice) ## for qqmath()

test <- function (x, data, main = TRUE,...){
#Say nothing about main shall give the current status
#(writing) the name of x)

#Saying 'main = FALSE' shall give no title at all

#Giving a specific main 
#(e.g. main = bquote(.("Let's write ") ~ sigma [0]^2))
#shall give this specific title

prepanel.ci <- function(x, y, se, subscripts, ...) {
    x <- as.numeric(x)
    se <- as.numeric(se[subscripts])
    hw <- 1.96 * se
    list(xlim = range(x - hw, x + hw, finite = TRUE))
}
panel.ci <- function(x, y, se, subscripts, pch = 16, ...) {
    panel.grid(h = -1, v = -1)
    panel.abline(v = 0)
    x <- as.numeric(x)
    y <- as.numeric(y)
    se <- as.numeric(se[subscripts])
    panel.segments(x - 1.96 * se, y, x + 1.96 * se, y, col = "black")

    panel.xyplot(x, y, pch = pch, ...)
    panel.xyplot(x, y, pch = pch, ...)
}
f <- function(nx) {
    xt <- x[[nx]]

    if(is.null(main)){
        mtit <- NULL
    }else if(is.expression(main)){
        mtit <- main
    }else if(main == TRUE){
        mtit <- nx
    }else{
        mtit <- main
    }
    if (!is.null(pv <- attr(xt, "postVar"))) {
        d <- dim(pv)
        se <- vapply(seq_len(d[1]), function(i) sqrt(pv[i, 
            i, ]), numeric(d[3]))
        nr <- nrow(xt)
        nc <- ncol(xt)
        ord <- unlist(lapply(xt, order)) + rep((0:(nc - 1)) * 
            nr, each = nr)
        rr <- 1:nr
        ind <- gl(nc, nr, labels = names(xt))

        xyplot(rep(qnorm((rr - 0.5)/nr), nc) ~ unlist(xt)[ord] | 
            ind[ord], se = se[ord], prepanel = prepanel.ci, 
            panel = panel.ci, scales = list(x = list(relation = "free")), 
            ylab = "Standard normal quantiles", xlab = NULL, main = mtit, ...)
    }
    else {
        qqmath(~values | ind, stack(xt), scales = list(y = list(relation = "free")), 
            xlab = "Standard normal quantiles", ylab = NULL, main = mtit, ...)
    }
}
sapply(names(x), f, simplify = FALSE)
}

fit <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)

ranef_fit <- ranef(fit, condVar = TRUE)

test(ranef_fit) #has title "Subject"
test(ranef_fit, main = TRUE) #has title "Subject"
test(ranef_fit, main = FALSE) #has no title
test(ranef_fit, main = expression("Let's write " ~ sigma [0]^2))#has the expression as title
test(ranef_fit, main = bquote(.("No this works") ~ sigma [0]^2))#has the bquote as title
Qaswed
  • 3,649
  • 7
  • 27
  • 47