Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format multiple geom_sf legends

Tags:

r

ggplot2

sf

I am dealing with multiple sf geometries in ggplot and would like to display legend in the form of a point, a line, and a square (for the polygon). However, geom_sf legend combines my geometry features (i.e. combining line and point) displayed below:

library(ggplot2)
library(sf)

poly1 <- cbind(lon = c(5, 6, 7, 5), lat = c(52, 53, 51, 52))

poly <- st_sf(st_sfc(st_polygon(list(poly1))))
line <- st_sf(st_sfc(list(st_linestring(cbind(lon = c(5.5, 4.5), lat = c(53.5, 54.5))))))
point <- st_sf(st_sfc(st_point(cbind(lon = 5.5, lat = 52.7))))

ggplot() +
  geom_sf(data = poly, aes(fill = "A")) +
  geom_sf(data = point, aes(colour = "B"), show.legend = "point") +
  geom_sf(data = line, aes(colour = "C"), show.legend = "line") +
  scale_fill_manual(values = c("A" = "yellow")) +
  scale_colour_manual(values = c("B" = "pink", "C" = "purple")) +
  theme_minimal()

enter image description here

I would like three separate legends, a single yellow square, a pink point, and a purple line on the same image illustrated below. It is only the case when I plot individual geometry but not the combination of three.

enter image description here

enter image description here

enter image description here

I looked up similar topics, but none of them dealt with point geometries i.e. https://github.com/tidyverse/ggplot2/issues/2460

Would anyone offer any insight on this?

GitHub issue: https://github.com/tidyverse/ggplot2/issues/2763

like image 742
Jane Avatar asked Jul 16 '18 23:07

Jane


2 Answers

Inspired by the comment from @Axeman, this issue and this post, the problem is solved using the override.aes argument in guide_legend():

library(ggplot2)
library(sf)

poly1 <- cbind(lon = c(5, 6, 7, 5), lat = c(52, 53, 51, 52))

poly <- st_sf(st_sfc(st_polygon(list(poly1))))
line <- st_sf(st_sfc(list(st_linestring(cbind(lon = c(5.5, 4.5), lat = c(53.5, 54.5))))))
point <- st_sf(st_sfc(st_point(cbind(lon = 5.5, lat = 52.7))))

ggplot() +
  geom_sf(data = poly, aes(fill = "A")) +
  geom_sf(data = point, aes(colour = "B"), show.legend = "point") +
  geom_sf(data = line, aes(colour = "C"), show.legend = "line") +
  scale_fill_manual(values = c("A" = "yellow"), name = NULL,
                    guide = guide_legend(override.aes = list(linetype = "blank", shape = NA))) +
  scale_colour_manual(values = c("B" = "pink", "C" = "purple"), name = NULL,
                      guide = guide_legend(override.aes = list(linetype = c("blank", "solid"), 
                                                               shape = c(16, NA)))) +
  theme_minimal() 

enter image description here

like image 183
Jane Avatar answered Nov 12 '22 17:11

Jane


I know how to seperate the legends, they only get combined now because you are mapping color twice. By mapping shape to the points and setting the color, you can get around that:

ggplot() +
  geom_sf(data = poly, aes(fill = "A")) +
  geom_sf(data = point, aes(colour = "B"), show.legend = "point") +
  geom_sf(data = line, aes(shape = "C"), show.legend = "line", color = 'purple') +
  scale_fill_manual(name = NULL, values = c("A" = "yellow")) +
  scale_colour_manual(name = NULL, values = c("B" = "pink")) +
  scale_shape_discrete(
    name = NULL, 
    guide = guide_legend(override.aes = list(color = 'purple'))) +
  theme_minimal()

enter image description here

But: the point and line are still showing up in all three legends. I don't think they should! Perhaps you can fill a github issue.

like image 4
Axeman Avatar answered Nov 12 '22 17:11

Axeman