geom_lollipop() by the Chartettes

>UPDATE: Changed code to reflect the new `horizontal` parameter for `geom_lollipop()`

I make a fair share of bar charts throughout the day and really like switching to lollipop charts to mix things up a bit and enhance the visual appeal. They’re easy to do in `ggplot2`, just use your traditional `x` & `y` mapping for `geom_point()` and then use (you probably want to call this first, actually) `geom_segment()` mapping the `yend` aesthetic to `0` and the `xend` aesthetic to the same thing you used for the `x` aesthetic. But, that’s alot of typing. Hence, the need for `geom_lollipop()`.

I’ll build this example from one [provided by Stephanie Evergreen](http://stephanieevergreen.com/lollipop/) (that one’s in Excel). It’s not much code:

df <- read.csv(text="category,pct
Other,0.09
South Asian/South Asian Americans,0.12
Interngenerational/Generational,0.21
S Asian/Asian Americans,0.25
Muslim Observance,0.29
Africa/Pan Africa/African Americans,0.34
Gender Equity,0.34
Disability Advocacy,0.49
European/European Americans,0.52
Veteran,0.54
Pacific Islander/Pacific Islander Americans,0.59
Non-Traditional Students,0.61
Religious Equity,0.64
Caribbean/Caribbean Americans,0.67
Latino/Latina,0.69
Middle Eastern Heritages and Traditions,0.73
Trans-racial Adoptee/Parent,0.76
LBGTQ/Ally,0.79
Mixed Race,0.80
Jewish Heritage/Observance,0.85
International Students,0.87", stringsAsFactors=FALSE, sep=",", header=TRUE)

# devtools::install_github("hrbrmstr/ggalt")
library(ggplot2)
library(ggalt)
library(scales)

gg <- ggplot(df, aes(y=reorder(category, pct), x=pct))
gg <- gg + geom_lollipop(point.colour="steelblue", point.size=3, horizontal=TRUE)
gg <- gg + scale_x_continuous(expand=c(0,0), labels=percent,
                              breaks=seq(0, 1, by=0.2), limits=c(0, 1))
gg <- gg + coord_flip()
gg <- gg + labs(x=NULL, y=NULL, 
                title="SUNY Cortland Multicultural Alumni survey results",
                subtitle="Ranked by race, ethnicity, home land and orientation\namong the top areas of concern",
                caption="Data from http://stephanieevergreen.com/lollipop/")
gg <- gg + theme_minimal(base_family="Arial Narrow")
gg <- gg + theme(panel.grid.major.y=element_blank())
gg <- gg + theme(panel.grid.minor=element_blank())
gg <- gg + theme(axis.line.y=element_line(color="#2b2b2b", size=0.15))
gg <- gg + theme(axis.text.y=element_text(margin=margin(r=-5, l=0)))
gg <- gg + theme(plot.margin=unit(rep(30, 4), "pt"))
gg <- gg + theme(plot.title=element_text(face="bold"))
gg <- gg + theme(plot.subtitle=element_text(margin=margin(b=10)))
gg <- gg + theme(plot.caption=element_text(size=8, margin=margin(t=10)))
gg

And, I’ll reiterate Stephanie’s note that the data is fake.

download

Compare it with it’s sister bar chart:

download1

to see which one you think works better (it really does come down to personal aesthetics choice).

You can find it in the development version of [`ggalt`](https://github.com/hrbrmstr/ggalt). The API is not locked in yet so definitely provide feedback in the issues.

Cover image from Data-Driven Security
Amazon Author Page

18 Comments geom_lollipop() by the Chartettes

  1. Pingback: geom_lollipop() by the Chartettes – Mubashir Qasim

  2. Matti

    This is great, thank you!

    Is there a reason for repeatedly updating the gg object, instead of saving the final object in one go? (That is gg <- gg + …, instead of gg <- … + … + …)

    Reply
    1. hrbrmstr

      for me? yes. it allows me to cut/paste or snippet in things without worrying about trailing +‘s and silly cascading indents. Doing it this way speeds up my workflow and has no other speed deficiencies/overhead. Each assignment is a distinct operation. Good plots require alot of tweaking and if you’re producing production quality outputs, you’ll end up saving time with this idiom.

      other folks can do what works for them :-)

      Reply
  3. hadleywickham

    I think the big question is which direction the default lollipop should go (i.e. vertical vs. horizontal). Pretty much all built-in geoms are vertical, but ggstance provides a whole bunch of horizontal versions.

    Reply
    1. hrbrmstr

      Aye. The examples I’ve seen tend to have them horizontal. Lemme make this an issue in the gh repo and see if I can get others to weigh in as well.

      Reply
  4. baptiste auguie (@tpab)

    i always picture lollipops as rainbow-coloured spirals – imagine my disappointment when I followed the link and saw blue dots. Can you give an option to pass an eye-candy grob?

    library(grid)
     
    lollipopGrob <- function(x, y, size, turns=3){
     
      theta <- seq(0, turns*2*pi, length=120)
      xx <- unit(x, "npc") + unit(size*theta/max(theta)*cos(theta+pi), "mm")
      yy <- unit(y, "npc") + unit(size*theta/max(theta)*sin(theta+pi), "mm")
      segmentsGrob(head(xx, -1), head(yy, -1), tail(xx, -1), tail(yy, -1), 
                   gp=gpar(col=hcl(seq(0,360,length=12), 90, 70), lwd=5))
    }
     
    l <- lollipopGrob(0.5, 0.5, 5)
    grid.newpage()
    grid.segments(0, 0.5, 0.5, 0.5)
    grid.draw(l)
    Reply
    1. hrbrmstr

      geom_dumbell() is a super gd idea (and I’m ashamed to say it didn’t cross my mind). May have time to get an alpha version out this week. #ty

      Reply
  5. armadillo world headquarters

    This is way cool, er, um, but there’s another easy way to do it with regular ggplot with something like geom_bar(stat = "count", width=0.01), no?

    Reply
    1. armadillo world headquarters

      Sorry, the count bit was from something I was playing with. I actually wanted to post:
      geom_bar(width=0.01) +
      geom_point()

      Reply
  6. Pingback: Beating lollipops into dumbbells | rud.is

  7. Brian Bettencourt

    Hi, for some reason I get “could not find function “geom_lollipop” ” errors even though I load the ggalt library. Odd. Here’s a sample:

    library(ggalt)
    Warning: package ‘ggalt’ was built under R version 3.2.5

    here’s simple sample data

    foobar
    foo bar
    1 a 1
    2 b 2

    make a plot

    aPlot <- ggplot(data=foobar, aes(x=foo,y=bar))
    aPlot + geom_point()

    the above runs fine, makes a point graph. try to run lollipop and…

    aPlot + geomlollipop()
    Error: could not find function “geom
    lollipop”

    Doesn’t matter if I supply some params to lollipop, etc. Is it simply because I’m running R 3.2.4? I also tried running your source from github, and get errors for the pipe symbols you use. I guess that’s a magrittr (or whatever) thing?

    Reply
    1. Brian Bettencourt

      Ugh, sorry, didn’t know the cmd line copy/paste would end up looking like that in this comment system. Let’s try that again:

      library(ggalt) Warning: package ‘ggalt’ was built under R version 3.2.5

      here’s simple sample data

      foobar
      foo bar
      1 a 1
      2 b 2

      make a plot

      aPlot <- ggplot(data=foobar, aes(x=foo,y=bar)) aPlot + geom_point()

      the above runs fine, makes a point graph. try to run lollipop and…

      aPlot + geomlollipop() Error: could not find function “geomlollipop”

      Reply
      1. Brian Bettencourt

        Figured it out. Had to install dev version from github, and a bunch of dependencies. Works now, thanks-

        Reply
        1. hrbrmstr

          Thx, Brian (saw the GH issue as well, ++thx for that, too). As I replied to @egrason, whether Hadley or Thomas will admit it or not, they broke stuff in the latest ggplot2 release and I have yet to scrounge the time (seriously complex “real life” stuff started happening around July) to fix. I’ll try to get to it soon, tho. I think there are actual issues in ggplot2 itself that still need some tweaking, but I haven’t had time to put together a full example.

          Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.