0

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.)

1 Answer 1

1

I recommend you to use fortify function getting a data.frame. Then you can easily add any other kind of variable adding a new column:

concave.spdf2 <- fortify(concave.spdf)
concave.spdf2 <- dplyr::left_join(concave.spdf2,data.frame(id=as.character(1:3), ocean = c('P','A','A')))

ggplot() +
  geom_polygon(data = concave.spdf2,
               aes(x = long, y = lat, group = group, fill = ocean, colour = ocean)) 
1
  • 1
    Better to use the sf polygons and then geom_sf which doesn't require any fortify
    – Spacedman
    Commented May 1, 2022 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.