0

Here is my GitHub Repository

I used QGIS Desktop 2.14.0 with GRASS 7.0.3 to add data to USA shapefile, to create this, but when I run following code

setwd("C:/GIS/US_Governor")

library(ggmap)
library(rgdal)
library(rgeos)
library(maptools)
library(dplyr)
library(tidyr)
library(tmap)



gov <- readOGR(dsn = ".", layer = "Age_of_US_Governor_Mar_2016")
qtm(gov, fill = "Age_of_G_1", fill.title = "Age of US Governor", fill.style="fixed",
    fill.palette = "Blues",
    fill.breaks=c(40,50,60,70)) + 
  tm_layout(legend.position = c("right", "bottom"), bg.color="lightgreen") 

I get a tiny USA map with big legend .... how to increase size of map? Thanks!

enter image description here

Update

I added + bb(xlim=150) and I get error, Error: could not find function "bb"

I included library tmap, hence troubleshooting ....

setwd("C:/GIS/US_Governor")

library(ggmap)
library(rgdal)
library(rgeos)
library(maptools)
library(dplyr)
library(tidyr)
library(tmap)



gov <- readOGR(dsn = ".", layer = "Age_of_US_Governor_Mar_2016")
qtm(gov, fill = "Age_of_G_1", fill.title = "Age of US Governor", fill.style="fixed",
    fill.palette = "Blues",
    fill.breaks=c(40,50,60,70)) + 
  tm_layout(legend.position = c("right", "bottom"), bg.color="lightgreen") +
  bb(xlim=150)
Community
  • 1
  • 1
Rhonda
  • 1,661
  • 5
  • 31
  • 65
  • 5
    Your problem might be that some of the Aleutian Islands cross over the 180°E line so are plotted on the far right of the plot. The simplest solution to that would be to set the xlim – Richard Telford Mar 27 '16 at 19:33
  • @RichardTelford Thanks, will try this! – Rhonda Mar 27 '16 at 19:48
  • @RichardTelford Please see updated question – Rhonda Mar 27 '16 at 23:25
  • 1
    I would have tried xlim(0,150), without the bb(). But this is just a hack, if you care about the Aleutian Islands you will need to use a projection that doesn't split the map at 180° – Richard Telford Mar 28 '16 at 00:08
  • @RichardTelford I tried `+ xlim(0,150)` but same result as before. Will play around with it some more. Thanks! – Rhonda Mar 28 '16 at 00:58

2 Answers2

3

If you're willing to use some elbow grease & ggplot2, the following gets you:

  • faster plotting (your QGIS polygons are really far too detailed for a broad thematic map)
  • a decent map projection for the US with AK & HI repositioned
  • better breaks (there are really 4 groups)
  • better colors (viridis FTW)

I tried to annotate the code a bit, too.

library(sp)
library(rgeos)
library(rgdal)
library(maptools)
library(ggplot2)
library(ggalt)
library(ggthemes)
library(viridis)

# Read in your map w/data -------------------------------------------------

guvnah <- readOGR("Age_of_US_Governor_Mar_2016.shp",
                  "Age_of_US_Governor_Mar_2016",
                  stringsAsFactors=FALSE)
guvnah_dat <- guvnah@data

# Get a map with simpler polygons -----------------------------------------

URL <- "http://eric.clst.org/wupl/Stuff/gz_2010_us_040_00_20m.json"
fil <- basename(URL)
if (!file.exists(fil)) download.file(URL, fil)

# Handy function ----------------------------------------------------------

make_uniform <- function(SPDF) {
  # bivand & fowler
  pref <- substitute(SPDF)
  newSPDF <- spChFIDs(SPDF,
                      as.character(paste(pref, rownames(as(SPDF,"data.frame")),
                                         sep="_")))
  return(newSPDF)
}

# We'll need these projections later --------------------------------------

albers <- "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"
latlon <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"

# Read in the simpler map -------------------------------------------------

us <- readOGR(fil, "OGRGeoJSON", stringsAsFactors=FALSE)

# I have code that can move AK & HI but the coord are in meters 
# which is fine for albers but not for the generic longlat
# so we switch the lighter map to albers (briefly) and swap it
# back to longlat to prep for use of albers coord_proj in the
# event one wanted to add points or lines down the road.

us_aea <- spTransform(us, CRS(albers))
us_aea <- make_uniform(us_aea)

alaska <- us_aea[us_aea$NAME=="Alaska",]
alaska <- elide(alaska, rotate=-50)
alaska <- elide(alaska, scale=max(apply(bbox(alaska), 1, diff)) / 2.3)
alaska <- elide(alaska, shift=c(-2100000, -2500000))
proj4string(alaska) <- proj4string(us_aea)

hawaii <- us_aea[us_aea$NAME=="Hawaii",]
hawaii <- elide(hawaii, rotate=-35)
hawaii <- elide(hawaii, shift=c(5400000, -1400000))
proj4string(hawaii) <- proj4string(us_aea)

us_aea <- subset(us_aea, !(NAME %in% c("Alaska", "Hawaii", "Puerto Rico")))
us_aea <- make_uniform(us_aea)
us_aea <- rbind(us_aea, alaska, hawaii)

# Back to latlon & make it usable in ggplot2 ------------------------------

us <- spTransform(us_aea, CRS(latlon))
us_map <- fortify(us, region="NAME")

# Get your age data into decent breaks ------------------------------------

guvnah_dat$age_brks <- cut(guvnah_dat$Age_of_G_1, 
                           breaks=c(40, 50, 60, 70, 80), 
                           labels=c("40-50", "50-60", "60-70", "70-80"),
                           include.lowest=TRUE)

# Do the thing ------------------------------------------------------------

gg <- ggplot()
gg <- gg + geom_map(data=us_map, map=us_map,
                    aes(x=long, y=lat, map_id=id),
                    color="white", size=0.1, fill=NA)
gg <- gg + geom_map(data=guvnah_dat, map=us_map,
                    aes(fill=age_brks, map_id=NAME_1),
                    color="white", size=0.1)
gg <- gg + scale_fill_viridis(name="Age of U.S. Governors", discrete=TRUE)
gg <- gg + coord_proj(albers)
gg <- gg + theme_map()
gg <- gg + theme(legend.position="bottom")
gg

enter image description here

hrbrmstr
  • 77,368
  • 11
  • 139
  • 205
  • @hrbrmstr That is genius and absolutely beautiful! Will try this! But first, I need to review and understand the code. – Rhonda Mar 28 '16 at 20:09
  • @hrbrmstr what does `NAME_1` represent in `gg + geom_map(data=guvnah_dat, map=us_map, aes(fill=age_brks, map_id=NAME_1)` ? Thank you. – Basilique May 13 '20 at 09:58
3

@hrbrmstr Very nice map! Here's my tmap solution:

devtools::install_github("mtennekes/tmap/pkg") 
# in the current CRAN version, there was a little problem with mapping
# numeric variables with one feature (in this example, the insets)
library(tmap)
library(grid)

# read shape data from https://github.com/Sonihal/US_Governor_Age
gov <- read_shape("Age_of_US_Governor_Mar_2016.shp")

# download and read simplified shape
f <- tempfile()
download.file("http://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_us_state_20m.zip", destfile = f)
unzip(f, exdir = ".")
us <- read_shape("cb_2014_us_state_20m.shp")

# append gov data to this shape
us <- append_data(us, gov@data, key.shp = "NAME", key.data = "NAME_1")

# split US in three: contiguous, Alaska and Hawaii
us_cont <- us[!us$NAME %in% c("Alaska", "Hawaii", "Puerto Rico"), ]
us_AL <- us[us$NAME=="Alaska", ]
us_HI <- us[us$NAME=="Hawaii", ]

# plot contiguous states
tm_shape(us_cont, projection=2163) +
  tm_polygons("Age_of_G_1", title="Age of US Governor", style="fixed",
              palette="Blues",
              breaks=c(40,50,60,70, 80)) +
  tm_layout(frame=FALSE,
            legend.position = c("right", "bottom"), bg.color="lightgreen",
            inner.margins = c(.25,.02,.02,.02))

# create inset map of Alaska
map_AL <- tm_shape(us_AL, projection = 3338) +
  tm_polygons("Age_of_G_1", title="Age of US Governor", style="fixed",
              palette="Blues",
              breaks=c(40,50,60,70, 80),
              legend.show=FALSE) +
tm_layout(frame=FALSE, bg.color="lightgreen")

# create inset map of Hawaii
map_HI <- tm_shape(us_HI, projection = 3759) +
  tm_polygons("Age_of_G_1", title="Age of US Governor", style="fixed",
              palette="Blues",
              breaks=c(40,50,60,70, 80),
              legend.show=FALSE) +
  tm_layout(frame=FALSE, bg.color="lightgreen")

# plot insets
library(grid)
print(map_AL, vp=viewport(x=.15, y=.15, width=.3, height=.3))
print(map_HI, vp=viewport(x=.4, y=.1, width=.2, height=.1))

enter image description here

The code is based on https://github.com/mtennekes/tmap#2-us-choropleth

Martijn Tennekes
  • 1,951
  • 13
  • 19