3

I'm trying to make a map using sf and geom_sf from ggplot2, where a set of point data are colored using a continuous scale (-1 to 1), and a set of line data are colored using a discrete scale (a,b,c,d). However, I'm running into trouble when I'm using both discrete and continuous aesthetics in the same map. A similar question was posted here, but it didn't deal with mapped aesthetics.

Here's a simplified example:

#Libraries
library(sf)
library(tidyverse)

#Make point data
N <- 1000
pointdat <- data.frame(x=runif(N,-1,1),y=runif(N,-1,1),z=rnorm(N)) %>% 
  st_as_sf(coords=c('x','y'))

ggplot(pointdat)+geom_sf(aes(col=z)) #Plot point data - this works

enter image description here

#Make line data
linedat <- rbind(c(1,1),c(1,-1),c(-1,-1),c(-1,1),c(1,1))*1.1
linedat <- lapply(1:(nrow(linedat)-1),function(x) st_linestring(linedat[c(x,x+1),]))
linedat <- st_sf(geometry=st_sfc(linedat)) %>% mutate(type=factor(letters[1:4]))

ggplot(linedat)+geom_sf(aes(col=type)) #Plot line data - this works

enter image description here

#When I try to plot point and line data together, it throws an error
ggplot()+
  geom_sf(data=linedat,aes(col=type))+
  geom_sf(data=pointdat,aes(col=z))

#Error: Continuous value supplied to discrete scale

Clearly there's a conflict between the continuous (point data) and discrete (line data) aesthetics, but how do I get each call to geom_sf to use different color aesthetics for each dataset? Using inherit.aes = FALSE doesn't change anything. This doesn't appear to be a problem if different aesthetics (e.g. fill vs col) are used.

S. Robinson
  • 223
  • 1
  • 8
  • 1
    This question is a bit dated but basically covers the same topic. https://stackoverflow.com/q/11508902/12400385. I think you will have to use something like `geom_sf(data=pointdat, aes(fill=z), shape = 21)` – nniloc Sep 02 '21 at 17:24

1 Answers1

5

One option to achieve your desired result or more generally to have multiple color scales is to make use of the ggnewscale package like so:

# Libraries
library(sf)
#> Linking to GEOS 3.8.1, GDAL 3.2.1, PROJ 7.2.1
library(tidyverse)
library(ggnewscale)

set.seed(42)
N <- 1000
pointdat <- data.frame(x = runif(N, -1, 1), y = runif(N, -1, 1), z = rnorm(N)) %>%
  st_as_sf(coords = c("x", "y"))

linedat <- rbind(c(1, 1), c(1, -1), c(-1, -1), c(-1, 1), c(1, 1)) * 1.1
linedat <- lapply(1:(nrow(linedat) - 1), function(x) st_linestring(linedat[c(x, x + 1), ]))
linedat <- st_sf(geometry = st_sfc(linedat)) %>% mutate(type = factor(letters[1:4]))

ggplot() +
  geom_sf(data = linedat, aes(col = type)) +
  new_scale_color() +
  geom_sf(data = pointdat, aes(col = z))

stefan
  • 90,330
  • 6
  • 25
  • 51