1

I want to produce a horizontal dotchart with error bars, with a log x axis.

I've explored a few options and got the closest to what I want with errbar from the package Hmisc. But I don't want to label the y-axis for each data point. I've tried adding yaxt="n" but this doesn't seem to change it.

Any suggestions to suppress this? Or alternative ways to achieve such a dotplot? Thanks in advance.

Example code using the mtcars data set:

mtcars$model <-as.factor(rownames(mtcars))
mtcars$model <- reorder(mtcars$model, mtcars$mpg)

plot(mtcars$model, mtcars$mpg, type="n",yaxt="n")

with (
  data = mtcars,
  expr = errbar(mtcars$model, mtcars$mpg,mtcars$mpg-mtcars$drat,mtcars$mpg+mtcars$drat,log='x', add=T, pch=16, cap=.5,xlab="MPG", yaxt="n")
 )

(First time I've asked a question on Stack Overflow, so hope I have added all the information needed)

Thanks

Biruk Abebe
  • 2,235
  • 1
  • 13
  • 24
Jenni G
  • 35
  • 1
  • 4
  • If you look at the code you can readily see that the `plot` functions is specified with `axes=FALSE` and then `axis(2, ...)` is called, so the function is drawing it's own axis and it's not conditioned by any Boolean flag. Why wouldn't you use the `dotplot` function in lattice? – IRTFM Apr 27 '16 at 21:24
  • Hi, I can't figure out how to do the error bars in lattice otherwise I would do that @42- Any assistance would be very welcome – Jenni G May 01 '16 at 21:16

2 Answers2

3

Seems like this is something you can easily construct with base plotting primitives. With the data

x<-mtcars$mpg
x1<-mtcars$mpg-mtcars$drat
x2<-mtcars$mpg+mtcars$drat
y<-seq_along(x)

you can plot

par(mar=c(5,2,3,2)+0.1)
plot(c(x1,x2), c(y,y), type="n", axes=F, log="x", xlab="", ylab="")
segments(x1, y, x2, y)
points(x, y, pch=20)
axis(1)

This results in

simple dot plot with no y axis

MrFlick
  • 195,160
  • 17
  • 277
  • 295
0

Isolate the axis(2, ... )function and make conditional on a named argument:

myerrbar <- 
 function (x, y, yplus, yminus, cap = 0.015, main = NULL, sub = NULL, 
    xlab = as.character(substitute(x)), ylab = if (is.factor(x) || 
        is.character(x)) "" else as.character(substitute(y)), 
    add = FALSE, lty = 1, type = "p", ylim = NULL, lwd = 1, pch = 16, 
    errbar.col = par("fg"), Type = rep(1, length(y)), ..., yax=TRUE) 
{
    if (is.null(ylim)) 
        ylim <- range(y[Type == 1], yplus[Type == 1], yminus[Type == 
            1], na.rm = TRUE)
    if (is.factor(x) || is.character(x)) {
        x <- as.character(x)
        n <- length(x)
        t1 <- Type == 1
        t2 <- Type == 2
        n1 <- sum(t1)
        n2 <- sum(t2)
        omai <- par("mai")
        mai <- omai
        mai[2] <- max(strwidth(x, "inches")) + 0.25
        par(mai = mai)
        on.exit(par(mai = omai))
        plot(NA, NA, xlab = ylab, ylab = "", xlim = ylim, ylim = c(1, 
            n + 1), axes = FALSE, ...)
        axis(1)
        w <- if (any(t2)) 
            n1 + (1:n2) + 1
        else numeric(0)
        if (yax) {axis(2, at = c(seq.int(length.out = n1), w), labels = c(x[t1], 
            x[t2]), las = 1, adj = 1)}
           points(y[t1], seq.int(length.out = n1), pch = pch, type = type, 
            ...)
           segments(yplus[t1], seq.int(length.out = n1), yminus[t1], 
            seq.int(length.out = n1), lwd = lwd, lty = lty, col = errbar.col)
           if (any(Type == 2)) {
            abline(h = n1 + 1, lty = 2, ...)
            offset <- mean(y[t1]) - mean(y[t2])
            if (min(yminus[t2]) < 0 & max(yplus[t2]) > 0) 
                lines(c(0, 0) + offset, c(n1 + 1, par("usr")[4]), 
                  lty = 2, ...)
            points(y[t2] + offset, w, pch = pch, type = type, 
                ...)
            segments(yminus[t2] + offset, w, yplus[t2] + offset, 
                w, lwd = lwd, lty = lty, col = errbar.col)
            at <- pretty(range(y[t2], yplus[t2], yminus[t2]))
            axis(side = 3, at = at + offset, labels = format(round(at, 
                6)))
        }
        return(invisible())
    }
    if (add) 
        points(x, y, pch = pch, type = type, ...)
    else plot(x, y, ylim = ylim, xlab = xlab, ylab = ylab, pch = pch, 
        type = type, ...)
    xcoord <- par()$usr[1:2]
    smidge <- cap * (xcoord[2] - xcoord[1])/2
    segments(x, yminus, x, yplus, lty = lty, lwd = lwd, col = errbar.col)
    if (par()$xlog) {
        xstart <- x * 10^(-smidge)
        xend <- x * 10^(smidge)
    }
    else {
        xstart <- x - smidge
        xend <- x + smidge
    }
    segments(xstart, yminus, xend, yminus, lwd = lwd, lty = lty, 
        col = errbar.col)
    segments(xstart, yplus, xend, yplus, lwd = lwd, lty = lty, 
        col = errbar.col)
    return(invisible())
}

And ignore the waring:

myexpr = myerrbar(mtcars$model, mtcars$mpg,mtcars$mpg-mtcars$drat,mtcars$mpg+mtcars$drat,log='x', pch=16, cap=.5,xlab="MPG", yax=FALSE)

No need for with if you are going to supply the name of the dataframe for every arument.

IRTFM
  • 258,963
  • 21
  • 364
  • 487