I have a code below for generating a simple polar bar plot in ggplot for quadrant-based values (wind radii from a central point of latitude & longitude), which looks like this:
I want to extract these polar plots to a SpatialPolygons object, so I can plot them as polygons on a map similar to this:
Is there any method to extract ggplot objects like this to a SpatialPolygons, shapefile, or some kind of dataframe for plotting on a map with ggplot/ggmap? Even a suggestion to explore further would be useful. Thanks in advance.
My dataframe:
winds <- data.frame(WindField = c(34, 50, 64, 34, 50, 64, 34, 50, 64, 34, 50, 64),
Quadrant = c("NE", "NE", "NE", "SE", "SE", "SE",
"SW", "SW", "SW", "NW", "NW", "NW"),
Radius = c(222, 93, 37, 139, 46, 37, 74, 19, 9, 222, 93, 37))
quads <- c("NE", "SE", "SW", "NW")
My ggplot code:
ggplot() +
geom_col(data = winds,
aes(x = factor(Quadrant, levels = quads),
y = Radius,
fill = factor(WindField),
group = factor(Quadrant, levels = quads)),
stat = "identity", position = "identity", width = 1, color = 'black') +
scale_fill_manual(values = c("yellow", "orange", "red")) +
guides(fill = guide_legend(title = "Wind [kt]")) +
coord_polar() +
theme_bw() +
theme(plot.title = element_text(size = 16),
plot.subtitle = element_text(size = 12),
axis.title = element_text(size = 14),
axis.text.y = element_text(size = 12, face = 'bold'),
axis.text.x = element_text(size = 14, face = 'bold'),
legend.text = element_text(size = 13),
legend.title = element_text(size = 13),
panel.border = element_blank(),
legend.position = "bottom") +
labs(y = "Radius [km]", x='Quadrant')
I don't think shapefiles play very well with ggplot, but you can convert the plots (which are ggplot objects) into grob objects & add them to the map using annotation_custom()
.
Here's an example, assuming you wish to plot multiple bar plots using a single data frame source file that contains all the necessary information.
Step 0: Generate data
set.seed(123)
df <- data.frame(
plot.ID = rep(1:2, each = 12),
WindField = rep(c(34, 50, 64), times = 8),
Quadrant = rep(rep(c("NE", "SE", "SW", "NW"), each = 3), times = 2),
Radius = rpois(24, lambda = 50) *
rep(c(5, 2, 1), times = 8) * # ensure radii decreases as WindField increases
c(rep(sample(1:4), each = 3), # ensure each quadrant looks visually distinct
rep(sample(5:8), each = 3)) # & looks different between plots
)
# convert Quadrant / WindField to factors
df$Quadrant = factor(df$Quadrant, levels = c("NE", "SE", "SW", "NW"))
df$WindField = factor(df$WindField)
# add position for each plot (using Florida for illustration)
# note maximum radius of the largest plot
df <- left_join(df,
data.frame(plot.ID = 1:2,
lon = c(-82, -80),
lat = c(29, 26)),
by = "plot.ID") %>%
mutate(max.Radius = max(Radius))
> head(df)
plot.ID WindField Quadrant Radius lon lat max.Radius
1 1 34 NE 460 -82 29 1920
2 1 50 NE 232 -82 29 1920
3 1 64 NE 76 -82 29 1920
4 1 34 SE 1000 -82 29 1920
5 1 50 SE 496 -82 29 1920
6 1 64 SE 212 -82 29 1920
Verify what the plots would look like, on a normal plot:
ggplot(df,
aes(x = Quadrant, y = Radius, fill = WindField)) +
geom_col(position = "identity", width = 1, color = "black") +
scale_fill_manual(values = c("yellow", "orange", "red")) +
coord_polar() +
facet_grid(~plot.ID) +
theme_void()
Step 1: Create separate polar bar plot for each location, convert to grob object, & specify their positions
df.grobs <- df %>%
group_by(plot.ID, lon, lat, max.Radius) %>%
do(subplots = ggplot(.,
aes(x = Quadrant, y = Radius, fill = WindField)) +
geom_col(position = "identity", width = 1, color = "black",
alpha = 0.5, # increase transparency to see map underneath
show.legend = FALSE) + # don't show legend for individual grobs
scale_y_continuous(limits = c(0, unique(.$max.Radius))) +
scale_fill_manual(values = c("yellow", "orange", "red")) +
coord_polar() +
theme_void()) %>%
mutate(subgrobs = list(annotation_custom(ggplotGrob(subplots),
x = lon - 1, # change from 1 to other
y = lat - 1, # values if necessary,
xmax = lon + 1, # depending on the map's
ymax = lat + 1))) # resolution.
Step 2: Create map
library(ggmap)
p <- get_map("Florida", zoom = 7) %>%
ggmap() +
coord_fixed()
Step 3: Combine map with the list of bar plot grobs
p + df.grobs$subgrobs