# Layered shape and multivariate plots with grindr

## Rationale

When it comes to complex graphics, a grammar has proven powerful and ggplot2 is mastering them all. “Base graphics” provided by the base package graphics has still some merits to me yet it may be boring to build exactly what you want. In particular, working with a grouping structure is boring, and using magrittr’s pipes is impossible since all graphical primitives are deadends.

Working with a grouping structure is done with Momocs:::.fac_dispatcher and piping drawers/layers is solved b systematically (invisibly) propagating the object used for plotting whether it is a single shape, a Coo object or something with more components like a PCA object.

Here I briefly introduce grindr (short for __gr__aphics __i__s __n__ot __d__ead) drawers and layers that helped rewrite graphical functions of Momocs since version 1.2.5 (one released on CRAN). They are still quite experimental and I’m not fully happy yet with the drawers (used for plotting shapes) /layers (used for multivariate cartesian planes) dichotomy but it may end up as an independant package at some point.

## Drawers

Papers and drawers are used to represent a shape (as a matrix of coordinates) or a collection of shapes (as any Coo object, namely Out, Opn or Ldk). It all starts with a paper* function, the simplest one being paper.

bot[1] %>% paper # single shape

olea %>% paper   # Coo (here Opn) object

Close to nothing is obtained but a graph with coordinates is obtained and ready for plotting more shape elements.

bot[1] %>% paper %>% draw_outline

olea %>% paper %>% draw_curve

Here we start to see shapes and that’s pretty much what the stack function does. This behaviour is possible since all grindr functions propagate the object they use(d):

bot %>% paper_chess %>% draw_outline -> x

x
## Out (outlines)
##   - 40 outlines, 162 +/- 21 coords (in $coo) ## - 2 classifiers (in$fac):
## # A tibble: 40 x 2
##   type   fake
##   <fct>  <fct>
## 1 whisky a
## 2 whisky a
## 3 whisky a
## 4 whisky a
## 5 whisky a
## 6 whisky a
## # ... with 34 more rows
##   - also: $ldk Here we used a different paper, and at the exit of the cheapbabi pipe we assigned the (otherwise invisibly) returned value to x, here the untouched bot. All available papers are listed below: apropos("paper") ## [1] "paper" "paper_chess" "paper_dots" "paper_grid" "paper_white" Most of the time, we are interested in representing a grouping structure, eg using color. With cheapbabi it can be done easily by specifying a column from the $fac (see the vignette Momocs speed dating, section Architecture). Also more drawers can be add on top of draw_outline:

bot %>% paper_grid %>%
draw_outline(~type, bor=col_qual) %>%
draw_axes %>% draw_centroid %>% draw_firstpoint
## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

Let’s come back to grouping specification. It’s quite versatile, you can pass a formula, a factor on the fly, and for colors and others drawers a vectorof the proper length (eg the right number of levels), a palette, etc. See below:

paper(bot) %>% draw_outlines(~type, bor=col_qual)
## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

paper(bot) %>%
draw_outlines(factor(rep(1:5, 8)), bor=col_qual) %>%
draw_centroid(~type, pch=c(1, 3))
## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

## Warning in polygon(x[[i]][, 1], x[[i]][, 2], border = cols[i], col =
## fills[i], : "bor" is not a graphical parameter

For now, I won’t write too much about it, in case large parts are modified, but you should be able to navigate among drawers with ?papers and ?drawers

## Layers

When working with multivariate euclidean (eg when asp=1) we often need to do again and again the same plot to explore the resulting data, for instance drawing convex hulls, confidence ellipses, etc. I implemented this layered strategy mostly to generalize former plot.PCA and reuse large parts.

So far, you can easily customize plots with:

x <- bot %>% efourier(6) %>% PCA
plot_PCA(x, ~type) %>%
layer_fullframe %>%
layer_morphospace %>%
layer_points %>% layer_chull %>%
layer_eigen %>% layer_legend

It works pretty much the same way as drawers, you can access the full list with apropos("layer_") and ?layers.

Here again, I’ll write more once cheapbabi development will become stable.

All suggestions and comments are welcome!

• Done with love by Vincent Bonhomme <bonhomme.vincent@gmail.com>.
• Help/suggestions/review/critics are welcome.
• Sources are there