Currently, I am using United States Congressional District Shapefiles. I want to make a Cartogram using the steps laid out in the cartogram package. But I cannot seem to make it into the cartogram object using the cartogram_cont
function successfully.
Any help, advice, or insight you can offer in getting me past this point and closer to the cartogram would be incredibly helpful.
Please the bottom of the code for where the error occurs.
Thank you!
######################### Library #####################
library(sf)
library(tmap)
library(cartogram)
library(ggplot2)
library(ggmap)
library(maptools)
###################### Get Congress Map ###################
get_congress_map <- function(cong=113) {
tmp_file <- tempfile()
tmp_dir <- tempdir()
zp <- sprintf("http://cdmaps.polisci.ucla.edu/shp/districts%03i.zip",cong)
download.file(zp, tmp_file)
unzip(zipfile = tmp_file, exdir = tmp_dir)
fpath <- paste(tmp_dir, sprintf("districtShapes/districts%03i.shp",cong), sep = "/")
st_read(fpath)
}
cd114 <- get_congress_map(114)
################ Create Congressional District ID ###################
State_Dictonary <- rbind(data.frame(state.abb, STATENAME= state.name), data.frame(state.abb= "DC", STATENAME= "District Of Columbia"))
#Add DC
cd114.1 <- merge(State_Dictonary, cd114, by = c("STATENAME"))
unique(cd114$STATENAME)
#**************** Paste Zero infront of Single Districts ****************
cd114.1$district_code <- as.character(cd114.1$DISTRICT)
cd114.1$district_code[cd114.1$district_code == 98] <- "01" #Account for the weird code for DC
cd114.1$district_code[cd114.1$district_code == 0] <- "01" #Account for at large districts
cd114.1$district_code[cd114.1$district_code == 1] <- "01"
cd114.1$district_code[cd114.1$district_code == 2] <- "02"
cd114.1$district_code[cd114.1$district_code == 3] <- "03"
cd114.1$district_code[cd114.1$district_code == 4] <- "04"
cd114.1$district_code[cd114.1$district_code == 5] <- "05"
cd114.1$district_code[cd114.1$district_code == 6] <- "06"
cd114.1$district_code[cd114.1$district_code == 7] <- "07"
cd114.1$district_code[cd114.1$district_code == 8] <- "08"
cd114.1$district_code[cd114.1$district_code == 9] <- "09"
#************** Create CD in Data ****************
cd114.1$CD <- paste(cd114.1$state.abb, cd114.1$district_code, sep = "")
################ Create Fake Data TO Simulate My Own ########################
CD <- unique(cd114.1$CD)
Values <- sample(1:100, 436, replace = T)
Df <- data.frame(CD, Values)
################### Merge Shape File to Donor #####################
#******************** Merge Descriptive Stats *********************
Df.2 <- merge(x = Df, y = cd114.1, by = c("CD"), all.y = T)
################### Make SF Object ####################
SF.DF.1 <- st_as_sf(Df.2)
SF.DF.2 <- st_make_valid(SF.DF.1)
class(SF.DF.2)
################### Make cartogram ####################
#Follow Proceedure Laid out: https://cran.r-project.org/web/packages/cartogram/readme/README.html
# I use st_transform instead of spTransform beause I'm using an SF Ojbect
SF.DF.3 <- st_transform(SF.DF.1, CRS("+init=epsg:3395"))
cartogram_cont(SF.DF.3, "Value", itermax = 5)
#Error in Fij[distance <= radius[j]] <- Fbij[distance <= radius[j]] :
#NAs are not allowed in subscripted assignments
The geometry entry in row 87 is empty (MULTIPOLYGON EMPTY
). You can overcome this issue by:
library(dplyr)
SF.DF.3 <- st_transform(SF.DF.1, CRS("+init=epsg:3395")) %>%
filter(!st_is_empty(.))
Additionally, there's no column Value
included in you df, it's Values
;)
sf_ncont <- cartogram_ncont(SF.DF.3, "Values")
tm_shape(sf_ncont) + tm_polygons("Values", style = "jenks", legend.show = FALSE) +
tm_layout(frame = FALSE)
Note, I filtered out Alaska and Hawaii for the following plot, as well as used cartogram_ncont
instead of cartogram_cont
since the former operation is very time consuming.