Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fill in ggplot shapefile map using a variable?

I am trying to fill a US map where each state is filled in by mean salary (In the default colour scale). I have the shapefile, and a dataframe which looks like this (Data falsified):

data <- structure(list(State = c("Arkansas",
                           "Iowa",
                           "California",
                           "Idaho"),
                 MeanSalary = c(50000,60000,62000,55000)),
                 row.names=1:4, class = "data.frame")

Here is my code:

library(tidyverse)
library(rgdal)

map <- readOGR(dsn = ".", layer = "usamap")

PlotData <- merge(map, data, by = "State")

This all works so far. I can also make an empty map:

map_base <- ggplot(data = PlotData, mapping=(aes(x=long, y = lat, group = group)) +
geom_polygon(color = "black", fill = NA)
map_base

However, I can't fill in the map with the values.

map_base <- ggplot(data = PlotData, mapping=(aes(x=long, y = lat, group = group)) +
geom_polygon(color = "black", fill = PlotData$MeanSalary)
map_base

I get this error:

Error: Aesthetics must be either length 1 or the same as the data (2834334): fill

What am I getting wrong?

like image 428
skipndipp Avatar asked May 26 '26 10:05

skipndipp


1 Answers

Here I provided two solutions to plot polygons using ggplot2.

Solution 1: geom_sf

sf class is the next generation spatial data class in R. geom_sf can plot the sf object. To do this, we need to convert the sp object to sf object. Here I used the state spatial polygons from the USAboundaries package as an example.

library(tidyverse)
library(sf)
library(USAboundaries)

# Get the state data
state <- us_states()

# Check the class
class(state)
# [1] "sf"         "data.frame"

# Create example data frame
data <- structure(list(State = c("Arkansas",
                                 "Iowa",
                                 "California",
                                 "Idaho"),
                       MeanSalary = c(50000,60000,62000,55000)),
                  row.names=1:4, class = "data.frame")

# Merge data to state and filter for these records
state_filter <- state %>% 
  left_join(data, by = c("name" = "State")) %>%
  # Remove Hawaii, Alaska, and Puerto Rico to just focus on the rest states
  filter(!name %in% c("Hawaii", "Alaska", "Puerto Rico"))

# Plot the data
ggplot(state_filter) +
  geom_sf(aes(fill = MeanSalary))

enter image description here

Solution 2: ggspatial package

The ggspatial package can plot the sp object. So if you don't want to work with sf object, using ggspatial could be an option.

library(tidyverse)
library(sf)
library(USAboundaries)
library(sp)
library(ggspatial)

# Convert the sf object to sp object
state_filter_sp <- as(state_filter, "Spatial")

# Plot the data
ggplot() +
  annotation_spatial(state_filter_sp) +
  layer_spatial(state_filter_sp, aes(fill = MeanSalary))

enter image description here

like image 194
www Avatar answered May 28 '26 00:05

www



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!