2

I would like to be able to design custom shapes that I can plot on a scatterplot. I could accomplish this currently using groupings but this seems a clunky solution if I want to plot 5 or more shapes this way.

library(ggplot2)
hexpoints <- data.frame(x=c(sin(pi*(0:5)/3),0), y=c(cos(pi*(0:5)/3),0))/2

ggplot(hexpoints, aes(x,y)) + geom_polygon(colour="black",fill=NA)

hexpoints2 <- data.frame(x=c(hexpoints$x,hexpoints$x+1), y=hexpoints$y, 
                    group=rep(c(1:2), each=nrow(hexpoints)))

ggplot(hexpoints2, aes(x, y, group=group)) + 
  geom_polygon(colour="black",fill=NA)

enter image description here

r2evans
  • 141,215
  • 6
  • 77
  • 149
Francis Smart
  • 3,875
  • 6
  • 32
  • 58
  • 5
    Maybe you can create a function which takes the centers of your shapes and return the data.frame of them – abichat Jan 03 '19 at 15:38
  • 2
    Save your custom shape as an image and [use one of these answers](https://stackoverflow.com/q/2181902/903061). – Gregor Thomas Jan 03 '19 at 16:56
  • Nice point @Gregor, though don't those tend to not flow as well with vector graphics formats? – r2evans Jan 03 '19 at 17:36

1 Answers1

3

Following @abichat's suggestion:

point2pacman <- function(x, y, grp) {
  if (is.data.frame(x)) {
    y <- x$y
    x <- x$x
  }
  if (length(x) == 1L || length(y) == 1L) {
    x <- rep(x, max(length(x), length(y)))
    y <- rep(y, max(length(x), length(y)))
  }
  if (missing(grp)) grp <- seq_along(x)
  do.call("rbind.data.frame",
          Map(function(i, a, b)
            data.frame(grp = i,
                       x = a + c(sin(pi*(0:5)/3),0) / 2,
                       y = b + c(cos(pi*(0:5)/3),0) / 2),
            grp, x, y))
}

library(ggplot2)

hexpoints2 <- data.frame(x=c(0,1), y=c(0,0))
point2pacman(hexpoints2$x, hexpoints2$y)
#    grp             x     y
# 1    1  0.000000e+00  0.50
# 2    1  4.330127e-01  0.25
# 3    1  4.330127e-01 -0.25
# 4    1  6.123032e-17 -0.50
# 5    1 -4.330127e-01 -0.25
# 6    1 -4.330127e-01  0.25
# 7    1  0.000000e+00  0.00
# 8    2  1.000000e+00  0.50
# 9    2  1.433013e+00  0.25
# 10   2  1.433013e+00 -0.25
# 11   2  1.000000e+00 -0.50
# 12   2  5.669873e-01 -0.25
# 13   2  5.669873e-01  0.25
# 14   2  1.000000e+00  0.00
# similarly: point2pacman(hexpoints2)

ggplot(hexpoints2, aes(x, y)) + 
  geom_text(aes(label=label), color = "red") +
  geom_polygon(aes(group = grp), data=point2pacman(hexpoints2), color="black", fill=NA)

sample repeated-polygon plot

I used hexpoints2 as the "main" data for ggplot in case you had other things going on there, and then overrode the data used just for that geom_polygon call. I added geom_text here to demonstrate the benefit of this method. The next step in this would be to define your own geom_pacman function that does some of this yourself; I haven't done that much, so I went with something quick, though it should not be that difficult. (Deprecated docs here, it's likely to be included somewhere in https://ggplot2.tidyverse.org/.)

r2evans
  • 141,215
  • 6
  • 77
  • 149
  • This method brings back an old cobweb of a memory: Apple ]\[+ and ]\[e [shape tables](https://en.wikipedia.org/wiki/Shape_table). – r2evans Jan 03 '19 at 21:41