Home > Net >  Coloring polygons (made with concaveman) in ggplot by column
Coloring polygons (made with concaveman) in ggplot by column

Time:05-02

I'm adapting code for a map made by someone else that uses a package concaveman to generate concave hulls from points. The goal is to plot a number of different polygons in the oceans, and to color-code them by a grouping variable. The code works great to make a map of all the polygons and color-code them by identity:

library(sf)
library(concaveman) 
library(data.table)
library(ggplot2)

dat <- data.table(longitude = c(-131.319783, -131.141266, -131.08165, -131.079066, -130.894966, 
             -131.063783, -131.10855, -131.215533, -131.189816, -131.14565, 
             -131.200866, -131.046466, -130.94055, -130.928983, -130.7513, 
             -130.8406, -130.833433, -130.830666, -130.82205, -130.89, -63.3666666666667, 
             -63.3666666666667, -63.1666666666667, -64.1833333333333, -63.3166666666667, 
             -63.3, -63.85, -63.9333333333333, -63.9333333333333, -63.5833333333333, 
             -63.5833333333333, -63.7, -63.7, -63.2833333333333, -63.5833333333333, 
             -63.95, -64.1833333333333, -63.8833333333333, -63.8, -63.2166666666667, 
             -5.6788, -5.4408, -5.6835, -5.424, -5.6475, -5.4371, -5.6181, 
             -5.4446, -5.6753, -5.4366, -5.6746, -5.4448, -5.6642, -5.4411, 
             -5.666, -5.4408, -5.624, -5.4321, -5.6806, -5.4473),
           latitude = c(52.646633, 52.589683, 52.556516, 52.559816, 52.402916, 52.5983, 
             52.554216, 52.550883, 52.539166, 52.658216, 52.627966, 52.481733, 
             52.486033, 52.469033, 52.469166, 52.261833, 52.292133, 52.301066, 
             52.3523, 52.366966, 48.4666666666667, 48.4666666666667, 48.65, 
             49.0166666666667, 48.8166666666667, 48.8166666666667, 49.1, 48.8666666666667, 
             48.8666666666667, 48.8, 48.8166666666667, 48.4833333333333, 48.4833333333333, 
             48.8, 48.8166666666667, 48.8833333333333, 49.05, 49.0833333333333, 
             48.7166666666667, 48.6666666666667, 54.7201, 54.6033, 54.7191, 
             54.5733, 54.7225, 54.5923, 54.7261, 54.6076, 54.719, 54.5978, 
             54.7195, 54.6108, 54.7204, 54.6062, 54.7214, 54.5923, 54.7275, 
             54.592, 54.7207, 54.6188),
           group = c(rep('NEPac',20),rep('NWAtl',20),rep('NEAtl',20))
           )

split <- split(dat, dat$group)
split.sf <- lapply(split, st_as_sf, coords = c("longitude", "latitude"))
concave <- lapply(split.sf, concaveman, concavity = 3, length_threshold = 2)
concave.binded <- do.call('rbind', concave)
concave.spdf <- as_Spatial(concave.binded)

ggplot()  
  geom_polygon(data = concave.spdf,
               aes(x = long, y = lat, group = group, fill = group, color = group)) 

However, I can't figure out how to fill the polygons by anything other than whatever group is. Here is my attempt:

concave.spdf$ocean <- c('P','A','A')

ggplot()  
  geom_polygon(data = concave.spdf,
               aes(x = long, y = lat, group = group, fill = ocean, color = ocean)) 

Which throws this error: Error in FUN(X[[i]], ...) : object 'ocean' not found

I think the issue is that split groups the polygons by identity when passed to concaveman, but if I change that, they won't plot correctly (because the points of different polygons will be merged). How do I keep the polygons plotted individually but color them by a grouping variable? (If it's possible I'd prefer to stick with concaveman for aesthetic reasons in the true plot [which is much more complicated than this reprex] -- I know that if I use a different approach to plotting the polygons this would be easier.)

CodePudding user response:

The simplest way to do this is by adding a scale_fill_manual:

ggplot()  
  geom_polygon(data = concave.spdf,
               aes(x = long, y = lat, group = group, fill = group))  
  scale_fill_manual(values = c("red", "green", "blue"),
                    labels = c("Ocean 1", "Ocean 2", "Ocean 3"))

enter image description here

Arguably, a better method is to convert to a simple features collection, to which you can add any columns you like, and automatically plot with geom_sf

concave.spdf <- st_as_sf(concave.spdf)
concave.spdf$ocean <- c("Ocean 1", "Ocean 2", "Ocean 3")

ggplot(concave.spdf)  
  geom_sf(aes(fill = ocean))

enter image description here

Note that this automatically gives the correct co-ordinate proportions too.

  • Related