--- title: 'Adding glyphs on scatterplot' author: "Wayne Oldford and Zehao Xu" date: "`r Sys.Date()`" bibliography: references.bib fontsize: 12pt link-citations: yes linkcolor: blue output: rmarkdown::html_vignette: toc: true geometry: margin=.75in urlcolor: blue graphics: yes vignette: > %\VignetteIndexEntry{Adding glyphs on scatterplot} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} header-includes: - \usepackage{graphicx} - \usepackage{epic} - \usepackage{color} - \usepackage{hyperref} - \usepackage{multimedia} - \PassOptionsToPackage{pdfmark}{hyperref}\RequirePackage{hyperref} - \newcommand{\code}[1]{\texttt{#1}} - \newcommand{\ve}[1]{\mathbf{#1}} - \newcommand{\pop}[1]{\mathcal{#1}} - \newcommand{\samp}[1]{\mathcal{#1}} - \newcommand{\subspace}[1]{\mathcal{#1}} - \newcommand{\sv}[1]{\boldsymbol{#1}} - \newcommand{\sm}[1]{\boldsymbol{#1}} - \newcommand{\tr}[1]{{#1}^{\mkern-1.5mu\mathsf{T}}} - \newcommand{\abs}[1]{\left\lvert ~{#1} ~\right\rvert} - \newcommand{\size}[1]{\left\lvert {#1} \right\rvert} - \newcommand{\norm}[1]{\left|\left|{#1}\right|\right|} - \newcommand{\field}[1]{\mathbb{#1}} - \newcommand{\Reals}{\field{R}} - \newcommand{\Integers}{\field{Z}} - \newcommand{\Naturals}{\field{N}} - \newcommand{\Complex}{\field{C}} - \newcommand{\Rationals}{\field{Q}} - \newcommand{\widebar}[1]{\overline{#1}} - \newcommand{\wig}[1]{\tilde{#1}} - \newcommand{\bigwig}[1]{\widetilde{#1}} - \newcommand{\leftgiven}{~\left\lvert~} - \newcommand{\given}{~\vert~} - \newcommand{\indep}{\bot\hspace{-.6em}\bot} - \newcommand{\notindep}{\bot\hspace{-.6em}\bot\hspace{-0.75em}/\hspace{.4em}} - \newcommand{\depend}{\Join} - \newcommand{\notdepend}{\Join\hspace{-0.9 em}/\hspace{.4em}} - \newcommand{\imply}{\Longrightarrow} - \newcommand{\notimply}{\Longrightarrow \hspace{-1.5em}/ \hspace{0.8em}} - \newcommand*{\intersect}{\cap} - \newcommand*{\union}{\cup} - \DeclareMathOperator*{\argmin}{arg\,min} - \DeclareMathOperator*{\argmax}{arg\,max} - \DeclareMathOperator*{\Ave}{Ave\,} - \newcommand{\permpause}{\pause} - \newcommand{\suchthat}{~:~} - \newcommand{\st}{~:~} --- ```{r setup, include=FALSE, warning=FALSE, message=FALSE} knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE, fig.align = "center", fig.width = 7, fig.height = 6, out.width = "60%", collapse = TRUE, comment = "#>", tidy.opts = list(width.cutoff = 65), tidy = FALSE) library(knitr) set.seed(12314159) imageDirectory <- "./images/glyph" dataDirectory <- "./data/glyph" path_concat <- function(path1, ..., sep="/") { # The "/" is standard unix directory separator and so will # work on Macs and Linux. # In windows the separator might have to be sep = "\" or # even sep = "\\" or possibly something else. paste(path1, ..., sep = sep) } library(ggplot2, quietly = TRUE) library(dplyr, quietly = TRUE) ``` Glyphs can be used as point symbols in a scatterplot to convey more information on each point. This information could range from providing a more evocative picture for each point (e.g., an airplane for flight data or a team's logo for sports data) to incorporating quantitative information (e.g., the values of other variables in a serial axes or star glyph or as a Chernoff face). In `ggmulti` we provide "glyph" layers to help add this information as point symbols on a plot [@loon]. ## Polygon glyphs Consider, for example, the lower 48 USA destinations of "nyc" flights in 2013. Each destination could be marked as a "airplane" polygon symbol and New York city is highlighted by a blue star. ```{r glyph_ggplot, fig.width=10} library(ggmulti) library(nycflights13) library(maps) # Flight destinations destinations <- nycflights13::airports %>% dplyr::rename(dest = faa) %>% dplyr::semi_join(nycflights13::flights, by = "dest") %>% dplyr::mutate(tzone = gsub("America/", "", tzone)) %>% dplyr::filter(lon > -151, lat < 55) # New York City coordinates NY <- data.frame( lon = -73.935242, lat = 40.730610 ) US <- map_data("state") %>% ggplot(aes(long, lat)) + geom_polygon(mapping = aes(group = group), color="black", fill="cornsilk") NYflightDestinationMap <- US + geom_polygon_glyph(data = destinations, mapping = aes(x = lon, y = lat), fill = "pink", # negate x to have each plane face west polygon_x = -x_airplane, polygon_y = y_airplane, alpha = 0.75) + geom_polygon_glyph(data = NY, mapping = aes(x = lon, y = lat), polygon_x = x_star, polygon_y = y_star, alpha = 0.75, fill = "blue") NYflightDestinationMap ``` Package "ggmulti" provides several polygon coordinates that can be used in `geom_polygon_glyph`, check `help("polygon_glyph", "ggmulti")`. ## Image glyphs We can also load image files (png, jpeg, etc) and set each image as a point glyph. Let's draw a chart of two 2020 Final NBA Teams. ```{r download images} library(png) img_path <- list.files(file.path(find.package(package = 'ggmulti'), "images"), full.names = TRUE) Raptors <- png::readPNG(img_path[grepl("Raptors", img_path)]) Warriors <- png::readPNG(img_path[grepl("Warriors", img_path)]) ``` ```{r image glyph NBA 2020} # Golden State Coordinate GoldenState <- data.frame( lon = -119.4179, lat = 36.7783 ) Toronto <- data.frame( lon = -79.3832, lat = 43.6532 ) # Get the Canada lakes cdn.lakes <- maps::map("lakes", plot=FALSE, fill=TRUE)$names[c(7,8,27,22, 25, 68:73, 82, 85 )] US + geom_polygon( data = maps::map("world", "Canada", fill=TRUE, plot=FALSE), mapping = aes(long, lat, group = group), fill="#ffcccb", colour = "black" ) + geom_polygon( # lakes in Canada data = maps::map("lakes", cdn.lakes, plot=FALSE, fill=TRUE), mapping = aes(long, lat, group = group), fill="lightblue", colour = "black" ) + geom_image_glyph(data = GoldenState, mapping = aes(x = lon, y = lat), images = Warriors, imagewidth = 1, imageheight = 1, colour = NA, size = 3) + geom_image_glyph(data = Toronto, mapping = aes(x = lon, y = lat), imagewidth = 1, imageheight = 1, colour = NA, size = 3, images = Raptors) + ggtitle("2019 NBA Finals") ``` ## Serialaxes glyphs Additionally, 'serial axes' can also be drawn as glyphs. ```{r serialaxes glyph} ggplot(iris) + geom_serialaxes_glyph( mapping = aes(Sepal.Length, Sepal.Width, colour = Species), # set serial axes data set (could be different from the original data) serialaxes.data = iris, # parallel or radial axes axes.layout = "radial", # sequence of serial axes axes.sequence = colnames(iris)[-5] ) ``` In this figure, we can tell the specie 'setosa' lays on the left top corner and the glyph shape is like a triangle that is very distinguishable from the rest two species. ## Reference