Mapping state borders with ggplot - r

I am attempting to create a ggplot map with both county and state boundaries. I am able to produce the map with county boundaries, but when adding the following line to get state borders as well, I run into an issue. The code is reproduced below.
ggplot2::geom_polygon(aes(x= long, y = lat, group = group), fill = NA, color = "black",
data = filter(us_map(), abbr %in% states_of_interest))
When I run this code, I get the error:
"Error in FUN(X[[i]], ...)
object 'long' not found". I am relatively unfamiliar with the us_map package, but I was told using long at lat for x and y would function correctly.
I have tried adding the command
"inherit.aes = FALSE"
upon other stack overflow post recommendations, but it did not solve the error.

The us_map function returns an object with x and y for lat/long. You can store the counties and states separately, then add them both to ggplot as polygons.
library(usmap)
states_of_interest <- c("CA","OR", "WA")
counties <- us_map(regions = "counties", include = states_of_interest)
states <- us_map(include = states_of_interest)
ggplot() +
geom_polygon(data = counties, aes(x = x, y = y, group = group), fill = NA, color = "black") +
geom_polygon(data = states, aes(x = x, y = y, group = group), fill = NA, color = "red") +
coord_equal()

Related

Can I make a map in R which shows two different categorical variables (e.g., income and region)?

I am trying to make a map of the U.S. which shows two categorical variables, for example the income group of the state and the region the state belongs in. The idea is to use the "fill" aesthetic to show the income level of each state, and then the "color" aesthetic to show the outlines of each region. The information that I am trying to communicate is that lower-income and higher-income states are clustered in certain regions.
An alternative would be to somehow show the regional boundaries with a bolder or thicker boundary than the state boundaries, but I am also unsure how to do this. Other ideas which communicate the same information would also be welcome.
Ideally, it would be some combination of the following two plots:
## Create map data
state_map_data <- map_data("state")
state_regions <- tibble(state_name = tolower(state.name), state.region,
as_tibble(state.x77)) %>%
mutate(income_cat = cut(Income, breaks = 3,
labels = c("low", "medium", "high")))
state_map_data <- state_map_data %>%
left_join(state_regions,
by = c("region" = "state_name"))
## Map with just income
p1 <- ggplot() +
geom_polygon(data = state_map_data,
aes(x = long, y = lat, group = group,
fill = income_cat))
print(p1)
This generates the following map with income
## Map with just regions
p2 <- ggplot() +
geom_polygon(data = state_map_data,
aes(x = long, y = lat, group = group,
color = state.region))
print(p2)
This generates the following map with regions
## Map with both
p <- ggplot() +
geom_polygon(data = state_map_data,
aes(x = long, y = lat, group = group,
fill = income_cat)) +
geom_polygon(data = state_map_data,
aes(x = long, y = lat, group = group,
color = state.region))
print(p)
This does not produce the expected results of a map with both a color outline by region and filled states by income as seen here
The way you have your code you are drawing two sets of polygons, with state.region polygons on top of the income_cat polygons. Instead, you want to draw one set of polygons with the correct outline color and fill color:
ggplot() +
geom_polygon(data = state_map_data,
aes(x = long, y = lat, group = group,
fill = income_cat, color = state.region)
)

how to use gganimate package plot a dynamic map in R?

As I know gganimate has been in version 1.0.3,we can use transition_* function to plot a dynamic graph. But when I run following code ,there is an error :
Error in `$<-.data.frame`(`*tmp*`, "group", value = "") :
replacement has 1 row, data has 0
code:
library(ggmap)
library(gganimate)
world <- map_data("world")
world <- world[world$region!="Antarctica",]
data <- data.frame(state = c("Alabama","Alaska","Alberta","Alberta","Arizona"),
lon = c(-86.55,-149.52,-114.05,-113.25,-112.05),
lat = c(33.30,61.13,51.05,53.34,33.30)
)
ggplot()+
geom_map(data = world,
map = world,
aes(long,lat,map_id = region),
color = '#333300',
fill = '#663300') +
geom_point(data = data,
aes(x = lon, y = lat),
size = 2.5) +
geom_jitter(width = 0.1) +
transition_states(states = state)
You have no data defined in the top level ggplot() line, so state in transition_* comes out of nowhere.
It's also unclear to me why you have a geom_jitter level in your code. Like transition_*, it has no top level data / aesthetic mappings to inherit, so it would have thrown an error too, had transition_* not triggered an error first. In addition, even if we add the mappings, given the range of lat/lon coordinates in your data, jittering by 0.1 is hardly going to matter visually.
You can try the following:
# put data in top level ggplot()
ggplot(data,
aes(x = lon, y = lat))+
geom_map(data = world,
map = world,
aes(long,lat,map_id = region),
color = '#333300', fill = '#663300',
# lighter background for better visibility
alpha = 0.5) +
geom_point(size = 2.5) +
# limit coordinates to relevant range
coord_quickmap(x = c(-180, -50), y = c(25, 85)) +
transition_states(states = state)

Combine multiple maps in R using ggplot2

This is a reproductible example of an issue I am facing. I am trying to create maps with ggplot2 in multiple stages. Here is the issue I face.
Consider the data borderwith the polygons of states in US at the Mexican border, and border.countywith the polygons of the counties in these states. The following code allows you to get the data:
library(maps)
library(ggmap)
library(ggplot2)
USA <- get_googlemap(center = 'usa', zoom = 4,
style = 'administrative|element:labels|visibility:off')
us.df <- map_data("state")
border <- subset(us.df,
region %in% c("california","arizona","new mexico","texas"))
counties <- map_data("county")
border.county <- subset(counties,
region %in% c("california","arizona","new mexico","texas"))
Now I wan to create a map, with the background of a map from Google Maps, with the state polygons and the county borders. If I do the following, it works neatly:
Allmap <- ggmap(USA) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group),
data=border, color = "white") +
geom_polygon(aes(x = long, y = lat, group = group),
data=border.county, fill=NA, color="red")
Now if I wanted to create this map in multiple stages, I hit problems. I just want the county boundaries for background information (as sort of 'recurrent theme'), and I will create multiple maps with changing information at the state level. So I create the 'background map' with counties, which works fine:
Countmap <- ggmap(USA) +
geom_polygon(aes(x = long, y = lat, group = group),
data=border.county, fill=NA, color="red")
And now I try to combine it with the state maps:
Statmap <- ggmap(USA) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group),
data=border, color = "white") +
Countmap
That gives me the error:
Error: Don't know how to add o to a plot
How can I solve this? I can combine the maps in the other way (as in: Statmap <- Countmap + geom_polygon(aes(x = long, y = lat, fill = region, group = group), data=border, color = "white")); however, that puts the counties under the state boundaries.
I also know this specific problem has the easy solution of just drawing a map with the states first, and combine it with the counties in a second stage. However, in my real scenario, that is not an option because the recurrent theme of the map is something that needs to be drawn in second place : cities and geographic borders (like my county boundaries here).
This is the map I want to create:
If I understand your description correctly, you don't want to combine maps. You want to combine layers, specifically, to overlay the county outlines on changing state-level maps.
Try this:
# define county outlines as a geom_polygon layer
county.layer <- geom_polygon(aes(x = long, y = lat, group = group),
data = border.county, fill = NA, color = "red")
# add county.layer as the last layer to your state-level map
Statmap <- ggmap(USA) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group),
data=border, color = "white") +
county.layer
Statmap
Edit in response to comment
If you have multiple county layers to plot, place them in a list:
border.county2 <- subset(counties, region %in% c("montana"))
layer2 <- list(geom_polygon(aes(x = long, y = lat, group = group),
data = border.county2, fill = NA, color = "blue"),
geom_polygon(aes(x = long, y = lat, group = group),
data = border.county, fill = NA, color = "red"))
Statmap <- ggmap(USA) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group),
data=border, color = "white") +
layer2

color polygon boundaries by factor

I'm trying to highlight zones on a map based on an associated factor, like so:
My initial problem was that, because the boundaries are overlapping, the zones would display improperly, like this:
I fixed that by hackily subsetting the data, which resulted in the first picture.
#First Map With No Legend
p <- ggplot() +
geom_polygon(data = OpportunityAreas.df[OpportunityAreas.df$Opp_Area == 'Yes',],
aes(long,lat,group=group), fill = "#d2eef7", color = 'black') +
geom_polygon(data = OpportunityAreas.df[OpportunityAreas.df$Opp_Area == 'No',],
aes(long,lat,group=group), fill = "#d2eef7", color = 'orange') +
coord_map()
But now I have no legend and also it just seems like a poor solution. Is there a proper way to color polygon boundaries by an associated factor?
#Second Map With Improper Boundaries
p.improperly.drawn <- ggplot() +
geom_polygon(data = OpportunityAreas.df,
aes(long,lat,group=group, color = Opp_Area), fill = "#d2eef7") +
coord_map()
Your first solution needs only a small tweak to get what you are looking for: move the color arguments within the geom_polygon calls to a mapping = aes() call instead. For the first call, mapping = aes(color = 'black') and for the second geom_polygon call use mapping = aes(color = 'orange').
I do not have access to the OpportunityAreas.df in your example so I will use some generic mapping data for my example below.
library(ggplot2)
library(mapdata)
counties <- map_data("county")
ca_county <- subset(counties, region == "california")
ca_county$color <- cut(ca_county$group, 2, labels = c("A", "B"))
ggplot() +
aes(x = long, y = lat, group = group) +
geom_polygon(data = subset(ca_county, color == "A"),
mapping = aes(color = "A"),
fill = NA) +
geom_polygon(data = subset(ca_county, color == "B"),
mapping = aes(color = "B"),
fill = NA)

How do you combine a map with complex display of points in ggplot2?

I'm trying to plot points from study sites with a background map of Africa. I can create the two independently, but I am having a hard time overlaying them on top of eachother.
The map of Africa I am using is an Esri shapefile from maplibrary.org. It is available from my dropbox at https://www.dropbox.com/s/etqdw3nky52czv4/Africa%20map.zip. I have the points in a text file, also available from my drop box. https://www.dropbox.com/s/scvymytjsr5pvaf/SPM-437-22Nov12.txt. They refer to studies on molecular drug resistance of malaria parasites. I would like to plot them so that the color is the proportion of parasites with the drug resistant genetic marker and the size is the number of parasites tested.
Plotting the points independently:
qplot(Longitude, Latitude, data = d.spm.437, colour = Frc437, size = Tot437)
Plotting the map of Africa:
library(maptools)
africa = readShapePoly("Africa.shp")
africa.map = fortify(africa, region="COUNTRY")
qplot(long, lat, data = africa.map, geom="path", group=group)
Any help on putting these two together while preserving the display of the points would be appreciated.
Try something like this. Seems to work for me. I think some of your lat-long coordinates are wrong though. The fill colour for geom_point is currently set to Tot437 so you might want to change that.
library(ggplot2)
library(rgdal)
africa <- readOGR("c:/test", layer = "Africa")
africa.map = fortify(africa, region="COUNTRY")
africa.points = read.table("c:/test/SPM-437-22Nov12.txt", header = TRUE, sep = ",")
names(africa.points)[which(names(africa.points) == 'Longitude')] <- 'long' # rename lat and long for consistency with shp file
names(africa.points)[which(names(africa.points) == 'Latitude')] <- 'lat'
ggplot(africa.map, aes(x = long, y = lat, group = group)) +
geom_polygon(colour = "black", size = 1, fill = "white", aes(group = group)) +
geom_point(data = africa.points, aes(x = long, y = lat, fill = Tot437, group = NULL), size = 4, shape = 21, colour = "black", size = 3)
Incidentally, looking at your map you may have difficulty getting a good detailed view of individual areas, so one way to tackle that would be by subsetting, in this case with the data frames. You could do this:
africa.map <- africa.map[africa.map$id == 'Madagascar', ]
africa.points <- africa.points[africa.points$Country == 'Madagascar', ]
ggplot(africa.map, aes(x = long, y = lat, group = group)) +
geom_polygon(colour = "black", size = 1, fill = "white", aes(group = group)) +
geom_point(data = africa.points, aes(x = long, y = lat, fill = Tot437, group = NULL), size = 2, shape = 21, colour = "black", size = 2)
...which should get you something similar to this:

Resources