JW_r_newbie
JW_r_newbie

Reputation: 13

Draw a line between 2 zip code on US map in R

I have been trying to draw a straight line connecting 2 zip code in the US. So far I've only been able to plot points of each zip code in the US, but can't draw the line between them

Here is what my data look like. I am trying to draw 8 points on the US map and connect them, with 4 lines. I tried using zip.plot but it would only point points, not drawing a line

df1 <- data.frame(trip = c(1,2,3,4), zip1 = c(55803,87112,55107,66006), zip2=c(12909,93703,12205,78210))

df1
  trip  zip1  zip2
1    1 55803 12909
2    2 87112 93703
3    3 55107 12205
4    4 66006 78210

Upvotes: 1

Views: 343

Answers (1)

Ben
Ben

Reputation: 30549

Take a look at the code for zip.plot function, and you'll see it is straightforward. It will merge your zip code data with longitude and latitude data from data(zips). You'll notice it will plot points, but no function to connect them, and it doesn't return points plotted.

You could adapt a similar function that meets your needs. If you include library(muRL) you can load zip data by data(zips). After plotting the points, you can add lines to connect them based on trip variable.

For example, create a new function zip.plot.new:

library(muRL)
data(zips)

zip.plot.new <- function(data, map.type = "state", ...){
  data.z <- merge(data, zips[,c("zip", "lat", "lon")], by.x = "zip", by.y = "zip", all.x = TRUE)
  maps::map(map.type, ...)
  points(data.z$lon, data.z$lat, cex = 1, col = "black", pch = 20)
  mapply(lines, split(data.z$lon, data.z$trip), split(data.z$lat, data.z$trip))
}

This includes mapply(lines... to connect points by trip.

Then, you can use your data frame, convert to longer form, and call this new function:

library(tidyverse)

df1 %>%
  pivot_longer(cols = starts_with("zip_"), names_to = c(".value", "group"), names_sep = "_") %>%
  zip.plot.new(.)

zip code plot

Note that zip code 12909 was not matched in the data (appears not valid?).

Data

df1 <- data.frame(trip = c(1,2,3,4), 
                  zip_1 = c("55803","87112","55107","66006"), 
                  zip_2 = c("12909","93703","12205","78210"))

Edit: Here's a ggplot version:

library(ggmap)
library(maps)
library(ggplot2)
library(tidyverse)

MainStates <- map_data("state")

point_data <- df1 %>%
  pivot_longer(cols = starts_with("zip_"), names_to = c(".value", "group"), names_sep = "_") %>%
  mutate(zip = factor(zip, levels = levels(zips$zip))) %>%
  left_join(zips) 

ggplot() + 
  geom_polygon(data=MainStates, aes(x=long, y=lat, group=group), color = "black", fill = "white") +
  geom_point(data = point_data, aes(x = lon, y = lat, group = trip)) +
  geom_line(data = point_data, aes(x = lon, y = lat, group = trip)) +
  coord_fixed(1.3) +
  theme_nothing()

Upvotes: 1

Related Questions