pointrange with plus signs?

42 views
Skip to first unread message

Zack Weinberg

unread,
Oct 19, 2020, 10:33:14 AM10/19/20
to ggplot2
I have (heavily reduced) data with a categorical independent variable
and a continuous dependent variable, one point per category, and error
bars on that point. There are several built-in geoms for plotting
this sort of thing, but they all have trouble with the error bars
becoming invisible when they're very short -- they get hidden behind
the marker for the best estimate of the actual value.

Concretely, here is a sample script that generates two PDF plots (both
of which are attached, for your convenience) and you can see that the
error bar is invisible in one direction on both of the data points.

---
library(ggplot2)

d <- data.frame(
case = c("A", "B"),
obs = c(0.3, 0.6),
obs.lo = c(0.25, 0.59),
obs.hi = c(0.31, 0.7)
)

cairo_pdf("demo-points.pdf", width=2, height=3)
ggplot(d, aes(x=case, y=obs, ymin=obs.lo, ymax=obs.hi)) +
ylim(0,1) +
geom_pointrange()
invisible(dev.off())

cairo_pdf("demo-crossbar.pdf", width=2, height=3)
ggplot(d, aes(x=case, y=obs, ymin=obs.lo, ymax=obs.hi)) +
ylim(0,1) +
geom_crossbar()
invisible(dev.off())
---

What I would like is to plot the `y` aesthetic with a thin horizontal
line and the `ymin..ymax` aesthetic with a thick vertical line with
square endcaps, as shown in the attached "demo-plus.pdf" (which is a
hand edit of demo-crossbar.pdf). I can get the thick vertical line
with geom_linerange() but I can't figure out any way to get the thin
horizontal line. `geom_segment(aes(x=case-0.5, xend=case+0.5))` seems
like it ought to work but gives an error about non-numeric operands to
binary operators (presumably - and +). Can anyone suggest anything?

zw
demo-plus.pdf
demo-crossbar.pdf
demo-points.pdf

Ben Bolker

unread,
Oct 19, 2020, 10:39:35 AM10/19/20
to ggp...@googlegroups.com
I have sometimes cheated on this one by using pch=3 (a plus sign)
with an appropriately large size ...

Ron Crump

unread,
Oct 19, 2020, 10:52:29 AM10/19/20
to ggp...@googlegroups.com
Hi Zack,

> ---
> library(ggplot2)
>
> d <- data.frame(
> case = c("A", "B"),
> obs = c(0.3, 0.6),
> obs.lo = c(0.25, 0.59),
> obs.hi = c(0.31, 0.7)
> )

> `geom_segment(aes(x=case-0.5, xend=case+0.5))` seems
> like it ought to work but gives an error about non-numeric operands to
> binary operators (presumably - and +). Can anyone suggest anything?

I think the non-numeric thing is because you've got
case as a factor/character ,and then you're adding/
subtracting a half.

you could try setting case to be numeric 1 and 2 then just label
the points on the axis with 'A' and 'B'. Or something using
levels(), maybe.

(I haven't tried this possible solution by the way)

HTH,
Ron.

Zack Weinberg

unread,
Oct 19, 2020, 11:24:48 AM10/19/20
to Ron Crump, ggplot2
On Mon, Oct 19, 2020 at 10:52 AM Ron Crump <r.e....@warwick.ac.uk> wrote:
> > `geom_segment(aes(x=case-0.5, xend=case+0.5))` seems
> > like it ought to work but gives an error about non-numeric operands to
> > binary operators (presumably - and +). Can anyone suggest anything?
>
> I think the non-numeric thing is because you've got
> case as a factor/character ,and then you're adding/
> subtracting a half.

Yes. This (adding a numeric constant to a categorical value that's
been mapped onto a linear aesthetic) does work in other contexts with
ggplot2, although I can't remember which ones at the moment.

> you could try setting case to be numeric 1 and 2 then just label
> the points on the axis with 'A' and 'B'. Or something using
> levels(), maybe.

I'll try that, thanks for the idea.

zw
Reply all
Reply to author
Forward
0 new messages