Skip navigation

>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.

16 Comments

  1. 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 <- … + … + …)

    • 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 :-)

  2. 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.

    • 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.

  3. 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)
  4. Any intention to generalise this type of plot to support ‘dumbbell plots’ or a seperate geom_dumbbell? I really like your snippet of code (https://gist.github.com/hrbrmstr/0d206070cea01bcb0118) for those plots, and they feel similar…

    • 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

    • armadillo world headquarters
    • Posted 2016-04-13 at 19:04
    • Permalink
    • Reply

    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?

      • armadillo world headquarters
      • Posted 2016-04-13 at 19:06
      • Permalink
      • Reply

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

  5. 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?

    • 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”

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

        • 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.


2 Trackbacks/Pingbacks

  1. […] article was first published on R – rud.is, and kindly contributed to […]

  2. By Beating lollipops into dumbbells | rud.is on 10 May 2016 at 6:31 am

    […] after I added lollipop charts to ggalt I had a few requests for a dumbbell geom. It wasn’t difficult to do modify the underlying […]

Leave a Reply

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