We want to create a graph/legend that uses shape to code one factor and color for another factor, and have the legend like a table, columns for one factor and rows for the other. The trick is, the legend labels have to be different in the two columns, something like this mockup:
Here are test data and a failed attempt. The factor "fromto" represents the columns; "match" the rows, linking the two elements that should have the same color.
library(ggplot2)
library(sf)
# Map limits
XLIM <- c( -112.2, -104 )
YLIM <- c( 33.8, 39.8 )
# DUMMY DATA
DAT <- "fromto match label lat long
Procurement flaghi 1-2 39.73921 -103.99030
Procurement flaglo 2-3 39.06831 -107.56443
Procurement pine 3-4 35.09633 -105.64020
Procurement taos 4-5 35.19934 -110.65155
Procurement crip 5-6 38.57335 -110.54645
Deployment flaghi 6-7 39.73921 -104.99030
Deployment flaglo 7-8 39.06831 -108.56443
Deployment pine 8-9 35.09633 -106.64020
Deployment taos 9-10 35.19934 -111.65155
Deployment crip 10-11 38.57335 -109.54645"
DAT <- read.table( text=DAT, header=TRUE, stringsAsFactors=FALSE )
DAT <- st_as_sf(x = DAT,
coords = c("long", "lat"),
crs = 4326 )
DAT$fromto <- factor(DAT$fromto)
DAT$match <- factor(DAT$match)
DAT$label <- factor(DAT$label)
p <- ggplot()
geom_sf( DAT, mapping=aes( shape=fromto, color=match ), size=3 )
scale_shape_manual( values=c(16,3), name=NULL )
scale_color_manual( values=c("red", "orange", "blue", "black", "green"),
labels=DAT$label, name=NULL )
coord_sf( xlim=XLIM, ylim=YLIM, crs=26912, default_crs=4326 )
p
CodePudding user response:
Using ggnewscale
you could try...
library(ggplot2)
library(sf)
library(ggnewscale)
# Map limits
XLIM <- c( -112.2, -104 )
YLIM <- c( 33.8, 39.8 )
# DUMMY DATA
DAT <- "fromto match label lat long
Procurement flaghi 1-2 39.73921 -103.99030
Procurement flaglo 2-3 39.06831 -107.56443
Procurement pine 3-4 35.09633 -105.64020
Procurement taos 4-5 35.19934 -110.65155
Procurement crip 5-6 38.57335 -110.54645
Deployment flaghi 6-7 39.73921 -104.99030
Deployment flaglo 7-8 39.06831 -108.56443
Deployment pine 8-9 35.09633 -106.64020
Deployment taos 9-10 35.19934 -111.65155
Deployment crip 10-11 38.57335 -109.54645"
DAT <- read.table(text = DAT, header = TRUE)
DAT <- st_as_sf(x = DAT,
coords = c("long", "lat"),
crs = 4326 )
# split data for to enable dual legend based on colour
dat_p <- DAT[DAT$fromto == "Procurement", ]
dat_d <- DAT[DAT$fromto == "Deployment", ]
ggplot()
geom_sf(dat_p, mapping = aes(color = match), shape = 3 , size=3 )
scale_color_manual(values = c("red", "orange", "blue", "black", "green"),
labels = dat_p$label,
name = "Procurement" )
new_scale_colour()
geom_sf(dat_d, mapping = aes(color = match), size=3 )
scale_color_manual( values = c("red", "orange", "blue", "black", "green"),
labels = dat_d$label,
name = "Deployment" )
coord_sf(xlim = XLIM,
ylim = YLIM,
crs = 26912,
default_crs = 4326)
theme(legend.direction = "vertical",
legend.box = "horizontal",
legend.position = c(1.025, 0.55),
legend.justification = c(0, 1))
Created on 2021-12-24 by the reprex package (v2.0.1)