Home > Tutorials > How to remember point shape codes in R

How to remember point shape codes in R

April 24th, 2012

I suspect I am not unique in not being able to remember how to control the point shapes in R. Part of this is a documentation problem: no package ever seems to write the shapes down. All packages just use the “usual set” that derives from S-Plus and was carried through base-graphics, to grid, lattice and ggplot2. The quickest way out of this is to know how to generate an example plot of the shapes quickly. We show how to do this in ggplot2. This is trivial- but you get tired of not having it immediately available.

library(ggplot2)
ggplot(data=data.frame(x=c(1:16))) + geom_point(aes(x=x,y=x,shape=x))

Symbols1
Or if you are feeling more daring:

ggplot(data=data.frame(x=c(1:16))) + geom_point(aes(x=x,y=x,shape=x)) + 
   facet_wrap(~x,scales='free')

Symbols2

Update 4-25-2012

As Idris kindly pointed out in the comments the above no longer works. I suspect what changed is something in the transition to R2.15.0. The following hack does work:

sum <- ggplot()
for(i in 1:16) { 
   sum <- sum + 
      geom_point(data=data.frame(x=c(i)),aes(x=x,y=x),shape=i)
}
sum

The trick is outside the aes() it looks like an integer works and at least 16 values work (instead of only around 6 inside the aes()). Frankly we are doing a lot of work to dance around R’s delayed evaluation and variable binding rules in this case. The ggplot2 examples have always plugged factors into the shapes- but I had always assumed that was to densify the indexing (get all the shape numbers into an interval) and not a requirement for using the shape parameter. The online documentation of shape has always been a line of text of the form:

Aesthetic Default Related scales
shape 16 identity, manual, shape

Which to my mind doesn’t specify if you have to supply a factor or not. But you really should buy Professor Hadley Wickham’s excellent book: ggplot2: Elegant Graphics for Data Analysis (not an affiliate link). My copy (like almost everything else I own) just happens to be packed in a box right now, so I can not easily consult it.

And it looks like we do get some nice bug fixes with this update. The missing scales on some of the facet_wrap panes appear to be fixed (yey!):

ggplot(data=data.frame(x=c(1:16))) + geom_point(aes(x=x,y=x)) +
    facet_wrap(~x,scales='free')

Rplot


Be Sociable, Share!
Categories: Tutorials Tags: , , ,
  1. April 24th, 2012 at 22:15 | #1

    I get this error:

    > ggplot(data = data.frame(x=c(1:16))) + geom_point(aes(x=x, y=x, shape=x))
    Error: A continuous variable can not be mapped to shape

  2. April 25th, 2012 at 06:22 | #2

    @Idris
    I now get the same error (just upgraded to R2.15.0 after writing this). I can’t even work around it, for example:

    ggplot(data=data.frame(x=c(1:16))) + geom_point(aes(x=x,y=x,shape=factor(x)))

    only displays 6 shapes. Not sure what is going on, but thanks for the feedback.

  3. April 25th, 2012 at 07:15 | #3

    @Idris
    Thanks again for pointing that out. I have edited the article to include a crude work around.

  4. Tyler Rinker
    April 25th, 2012 at 08:55 | #4

    I had a similar idea a while back and use the following code in base:

    symbols <- function(){
    plot(x=rep(5:1, 5), y=rep(1:5, each=5), pch=25:1,
    ylim=c(1, 5.25), xlab="", ylab="",
    main="Symbols (pch)", axes=FALSE)
    text(25:1, x=rep(5:1, 5), y=rep(1:5, each=5)+.2, cex=.8)
    box()
    }

  5. Kevin Wright
    April 25th, 2012 at 13:12 | #5

    This is soooo much easier in base R

    plot(1:16, pch=1:16)

    Not to mention easier on the eyes without the gray background and grid lines.

  6. April 25th, 2012 at 14:15 | #6

    @Kevin Wright
    I actually like the gray background and grid lines. But you are right- the base call is much much easier.

  7. Edward Wallace
    April 25th, 2012 at 14:54 | #7

    To make this work in ggplot2 0.9.0, use scale_shape_identity. For example,
    ggplot(data=data.frame(x=1:25)) + geom_point(aes(x=x,y=x,shape=x)) + scale_shape_identity()

    or Kevin would appreciate the short version using qplot:
    qplot(x=1:25,y=1:25,shape=1:25) + scale_shape_identity()

    I put things from 1:25 as that’s how many shapes there are. Hadley in the book probably use code like this to make the figure:
    ggplot(data=data.frame(x=rep(1:5,5),y=rep(1:5,each=5),shape=1:25)) +
    geom_point(aes(x=x,y=y,shape=shape)) + scale_shape_identity() +
    geom_text(aes(x=x+.1,y=y-.1,label=shape))

    Different shapes that look the same when not filled have different fill properties revealed thus:
    ggplot(data=data.frame(x=rep(1:5,5),y=rep(1:5,each=5),shape=1:25)) +
    geom_point(aes(x=x,y=y,shape=shape),fill=’blue’,size=5) + scale_shape_identity() +
    geom_text(aes(x=x+.1,y=y-.1,label=shape))

    Thanks for prompting me to figure this out.

  8. April 25th, 2012 at 16:23 | #8

    @Edward Wallace

    Thanks, Edward. That helps a lot and I learned a lot.

  9. April 25th, 2012 at 16:24 | #9

    Well this totally did not go the way I expected. I thought I would just post how I plot the shapes (since they are not well documented). Now I feel made to look doubly foolish. First for not knowing about scale_shape_identity() (On http://had.co.nz/ggplot2/geom_point.html scale_shape() is used in examples but not documented and scale_shape_identity() is nowhere to be seen). Second this shouldn’t be a hard task with hidden complexity (and it is not a hard task in base graphics). ggplot2 is my favorite plotting package, but man that did not go well.

  10. April 26th, 2012 at 07:11 | #10

    Here is my attempt:

    ggplot(data=data.frame(x=c(0:25))) + geom_point(size=10, aes(x=x,y=x,shape=x)) +
    facet_wrap(~ x, scales=’free’) + xlab(”) + ylab(”) +
    scale_shape_identity() +
    opts(axis.text.x=theme_blank(), axis.text.y=theme_blank(),
    axis.ticks=theme_blank(), legend.position=’none’,
    panel.background=theme_blank(),
    panel.grid.major=theme_blank(),
    panel.border=theme_blank())

  11. April 26th, 2012 at 08:02 | #11

    @Jason Bryer
    I was about to say that that was just cruel in the number of modifiers. But that is really beautiful plot, good enough to print and tape up as a reminder.

  12. Edward Wallace
    April 26th, 2012 at 11:14 | #12

    Further thought reveals that Hadley has code to do all this in the ggplot2 documentation. Type ?shape and look at the bottom examples.

  13. April 26th, 2012 at 20:14 | #13

    @Jason Bryer
    Jason, I really like your article http://bryer.org/2012/graphic-parameters-symbols-line-types-and-colors-for-ggplot2 , it is a really useful reference on R plot features.

Comments are closed.