Looking at Land “Grant” Parcels That Benefitted Ohio State

Ohio’s largest and most prestigious college, “THE” Ohio State University, proudly displays its heritage as a Land Grant University. It even has a “Land Grant Fierce” section of its website.

In Columbus, the Land Grant Brewing Company has exploded in recent years, becoming a 40-person company in just five years. You can now see cans stamped with “Land Grant” at grocery stores from Cincinnati on up to Mansfield.

But this “Land Grant” pride masks that Ohio’s flagship educational system was not actually “granted” any land.

For the first time in history, High Country news has documented 97.5% of all the 1862 Morill Act land grants and traced them back to their benefactors. They have offered this project as part of a joint collaboration with other media outlets, and given Ohio’s history, we thought we would do a story on the Ohio legacy as well.

Our goal here is to make the land tangible- not just a parcel number on a piece of paper, but an actual picture that people can appreciate. Thanks to the power of R and the maps available through Google, we are able to place our readers actually in the scene. Or at least show quite a few of them. Here is the story on our site.

And here is how we did it:

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggmap)
## Loading required package: ggplot2
## Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
## Please cite ggmap if you use it! See citation("ggmap") for details.
library(sf)
## Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
library(rgdal)
## Loading required package: sp
## Warning: package 'sp' was built under R version 3.6.2
## rgdal: version: 1.4-4, (SVN revision 833)
##  Geospatial Data Abstraction Library extensions to R successfully loaded
##  Loaded GDAL runtime: GDAL 2.4.2, released 2019/06/28
##  Path to GDAL shared files: /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rgdal/gdal
##  GDAL binary built with GEOS: FALSE 
##  Loaded PROJ.4 runtime: Rel. 5.2.0, September 15th, 2018, [PJ_VERSION: 520]
##  Path to PROJ.4 shared files: /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rgdal/proj
##  Linking to sp version: 1.3-1
library(sp)
library(tigris)
## To enable 
## caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
## 
## Attaching package: 'tigris'
## The following object is masked from 'package:graphics':
## 
##     plot
options(tigris_class = "sf")
library(usmap)
library(geosphere)
library(mapview)
## Warning: package 'mapview' was built under R version 3.6.2
library(purrr)
library(imager)
## Warning: package 'imager' was built under R version 3.6.2
## Loading required package: magrittr
## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
## 
##     set_names
## The following object is masked from 'package:ggmap':
## 
##     inset
## 
## Attaching package: 'imager'
## The following object is masked from 'package:magrittr':
## 
##     add
## The following object is masked from 'package:sp':
## 
##     bbox
## The following objects are masked from 'package:stats':
## 
##     convolve, spectrum
## The following object is masked from 'package:graphics':
## 
##     frame
## The following object is masked from 'package:base':
## 
##     save.image
library(rvest)
## Loading required package: xml2
## 
## Attaching package: 'rvest'
## The following object is masked from 'package:purrr':
## 
##     pluck
library(magick)
## Warning: package 'magick' was built under R version 3.6.2
## Linking to ImageMagick 6.9.9.39
## Enabled features: cairo, fontconfig, freetype, lcms, pango, rsvg, webp
## Disabled features: fftw, ghostscript, x11

As per the authors: To cite ggmap in publications, please use:

D. Kahle and H. Wickham. ggmap: Spatial Visualization with ggplot2. The R Journal, 5(1), 144-161. URL http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf

First we need to bring the the data from all the parcels, from this link shared by High Country News.

treaties <- rio::import("Uni_State_Treaty_Summaries_3_7_20.xlsx")
universities <- rio::import("Universities_3_7_20.csv")
lands <- rio::import("Indigenous_Land_Cessions_3_7_20.csv")

Now we are just getting Ohio:

Ohio_treaties <- treaties %>% 
  filter(State_Abbrev=="OH")

Ohio_universities <- universities %>% 
  filter(State_Abbrev=="OH")

Now we are looking at mapping data. This is taken from the research of Robert Lee.

parcels <- rio::import("https://raw.githubusercontent.com/HCN-Digital-Projects/landgrabu-data/master/Morrill_Act_of_1862_Indigenous_Land_Parcels_Database/CSVs/Parcels.csv")

And now we filter for Ohio:

ohio_parcels <- parcels %>% 
  filter(LG_State=="OH")

How many acres benefitted Ohio?

sum(ohio_parcels$Acres)
## [1] 614325.3

How many states is this located in? (The parcels that were sold.)

unique(ohio_parcels$Loc_State)
##  [1] "MS" "MI" "MO" "FL" "KS" "NE" "IA" "WI" "MN" "CA" "SD" "OR" "CO" "WA"

Why were they sold?

unique(ohio_parcels$LG_Reason)
##  [1] "Patented under Morrill Act in favor of OH"                                      
##  [2] "Original patent reviewed"                                                       
##  [3] "Estimated: REBECCA J VAUGHN obtained 2 other patent(s), all in OH state grant"  
##  [4] "Estimated: ERICK ELLIFSON obtained 2 other patent(s), all in OH state grant"    
##  [5] "Estimated: BENNY GRAVES obtained 1 other patent(s), all in OH state grant"      
##  [6] "Estimated: MILLARD F VOSHELL obtained 1 other patent(s), all in OH state grant" 
##  [7] "Estimated: THORVALD N OIUM obtained 1 other patent(s), all in OH state grant"   
##  [8] "Patented under the Morrill Act in favor of OH"                                  
##  [9] "Estimated: KNUTE OLESON obtained 3 other patent(s), all in OH state grant"      
## [10] "Estimated: GEORGE CAMPBELL obtained 4 other patent(s), all in OH state grant"   
## [11] "Estimated: EDWARD T HOWARD obtained 4 other patent(s), all in OH state grant"   
## [12] "Estimated: OLIVER S BRYAN obtained 3 other patent(s), all in OH state grant"    
## [13] "Estimated: JAMES PARKIN obtained 4 other patent(s), all in OH state grant"      
## [14] "Estimated: ALVAH HAND obtained 3 other patent(s), all in OH state grant"        
## [15] "Estimated: MARY HUNGERFORD obtained 2 other patent(s), all in OH state grant"   
## [16] "Estimated: JAMES S CUMMINGS obtained 2 other patent(s), all in OH state grant"  
## [17] "Estimated: IRA C DIXON obtained 2 other patent(s), all in OH state grant"       
## [18] "Estimated: SIDNEY E SHEPARD obtained 2 other patent(s), all in OH state grant"  
## [19] "Estimated: DAVID T RICKEY obtained 2 other patent(s), all in OH state grant"    
## [20] "Estimated: INGALLS K BUCK obtained 2 other patent(s), all in OH state grant"    
## [21] "Estimated: WILLIAM H BUCK obtained 2 other patent(s), all in OH state grant"    
## [22] "Estimated: JANE E GRANNIS obtained 2 other patent(s), all in OH state grant"    
## [23] "Estimated: JOSEPH ERTMAN obtained 1 other patent(s), all in OH state grant"     
## [24] "Estimated: JOHN M BARR obtained 1 other patent(s), all in OH state grant"       
## [25] "Estimated: MARY R WHEELER obtained 1 other patent(s), all in OH state grant"    
## [26] "Estimated: AUGUST R BERG obtained 1 other patent(s), all in OH state grant"     
## [27] "Estimated: CHRISTIAN JOHANSON obtained 1 other patent(s), all in OH state grant"
## [28] "Patented under Morrill Act in favor of OH (see 0351-126AGSSD)"                  
## [29] "Patented under Morrill Act in favor of OH (see 0340-388AGSSD)"                  
## [30] "Estimated: FRANK COTTON obtained 1 other patent(s), all in OH state grant"      
## [31] "Estimated: JACOB STRUBLE obtained 1 other patent(s), all in OH state grant"     
## [32] "Estimated: MARY E BENNETT obtained 1 other patent(s), all in OH state grant"

Now that we have the parcels, we have to (add the shapefiles.)[https://github.com/HCN-Digital-Projects/landgrabu-data/blob/master/Morrill_Act_of_1862_Indigenous_Land_Parcels_Database/Shapefiles/README.md] These are mapping files that outline the shape of each parcel.

parcel_polygons <- st_read("Parcel_Polygons.shp")
## Reading layer `Parcel_Polygons' from data source `/Users/Lucia/Code/Land Grab/Parcel_Polygons.shp' using driver `ESRI Shapefile'
## Simple feature collection with 79360 features and 4 fields
## geometry type:  MULTIPOLYGON
## dimension:      XYZ
## bbox:           xmin: -124.5124 ymin: 28.82222 xmax: -81.65863 ymax: 49.00015
## epsg (SRID):    NA
## proj4string:    NA

Adding them together with MTRSA_LG: (That’s the column they have in common)

ohio_parcels_with_shapefiles <- inner_join(ohio_parcels, parcel_polygons, by = "MTRSA_LG")
## Warning: Column `MTRSA_LG` joining character vector and factor, coercing
## into character vector
#This creates a dataframe

ohio_shapefiles_with_parcels <- inner_join(parcel_polygons, ohio_parcels, by = "MTRSA_LG")
## Warning: Column `MTRSA_LG` joining factor and character vector, coercing
## into character vector
#This creates an SF object. 

We are creating two dataframes here because we need the different types later.

And visualize!(We will add the background map later.)

ggplot(ohio_parcels_with_shapefiles)+
  geom_sf(aes(geometry = geometry), color="black")

So now we run into a problem: We have spatial polygons, but we need to get the latitude and longitude of the middle for two reasons.

First, to get individual pictures, we will want to get google street view photos of the middle of each point.

Second, to show these on a map, we want to highlight the middle so that we can place a marker there. As per the terms of service, we can only use Google Street View photos with Google Maps. And the “my maps” function only accepts addresses or lat/long pairs. Unless all our readers download Google Earth. But most will read this on their phones, probably, so we want to make it mobile-friendly.

So we use a “centroid” function to get the center of each point.

ohio_shapefiles_with_parcels <- ohio_shapefiles_with_parcels %>% 
  mutate(center = st_centroid(geometry)) 

This returns a vector of sfc_POINT type, though. Then converting the center into a format we can work with.

ohio_shapefiles_with_parcels$center <- st_coordinates(ohio_shapefiles_with_parcels$center)

Okay, now we need to get the individual street views. We do this using the Google API. To do this, you will need your own account at console.cloud.google.com.

Here is a sample

#https://maps.googleapis.com/maps/api/streetview?size=400x400&location=43.37627,-82.87531&key=[ADD YOUR OWN GOOGLE API KEY HERE]

We are adding the center we got with the sf class dataframe back into the regular dataframe so we can work with it.

ohio_parcels_with_shapefiles <- cbind(ohio_parcels_with_shapefiles, ohio_shapefiles_with_parcels$center)

Now we are creating the Static Maps API call for Google as a new column in our dataframe.

ohio_parcels_with_shapefiles <- ohio_parcels_with_shapefiles %>%  
  mutate(pictureURL = paste0(
    "https://maps.googleapis.com/maps/api/streetview?size=400x400&location=",
    Y,
    ",",
    X,
    "&key=[ADD YOUR OWN GOOGLE API KEY HERE]"))

To save all the images:

#list_of_images <- map(ohio_parcels_with_shapefiles$pictureURL,image_read)

As this costs money, we are only running it once. But you would uncomment it to run. Just FYI, you cannot save or cache image objects between R sessions!

And then saving those images in your folder.

my_path <- "~/Code/Land Grab/Land Grab" #Or whatever your path is
for (i in 1:4060){
  image_write(list_of_images[[i]], path =  paste0(my_path,ohio_parcels_with_shapefiles$MTRSA_LG[[i]],".jpg"), format = "jpg")
}

Okay now we have some very beautiful photos!

One of the photos we got from Wisconsin. Look at those beautiful clouds. Now we are getting something tangible.

We then uploaded that to the Eye on Ohio website. (So that we don’t get charged for looking at a photo every time.)

Then we will connect that URL to the spreadsheet that we will upload to Google’s “My Maps”:

ohio_parcels_with_shapefiles <- ohio_parcels_with_shapefiles %>% 
  mutate(`Street View` = paste0("https://eyeonohio.com/wp-content/uploads/2020/07/",MTRSA_LG,".jpg")) %>% 
  select(-geometry) #So that we can get this in a CSV file

Unfortunately there are only 72 street views out of 4,411 parcels. 4060 of which we have mapping data for. This makes sense as as lot of these parcels are rural and might not have a street view close to them.

Google maps does have a (nearest roads function:)[https://developers.google.com/maps/documentation/roads/nearest]

Here is a sample API call: https://roads.googleapis.com/v1/nearestRoads?points=43.37624,-82.87728|43.37990,-82.87745|43.38353,-82.87761&key=[ADD YOUR OWN GOOGLE API KEY HERE]

This is the real json return for the closest road to a parcel up in Michigan that benefitted Ohio State.

This is the real json return for the closest road to a parcel up in Michigan that benefitted Ohio State.

But even that doesn’t aways return coordinates that have a picture. It’s the nearest street not the nearest streetview.

Here the dot shows the nearest street to the parcel, but the blue lines show the nearest street view pictures

Here the dot shows the nearest street to the parcel, but the blue lines show the nearest street view pictures

So it wouldn’t be possible to know, if we got a street view of a point on the perimeter, if the camera was facing toward the parcel or away from it. We could do it manually, by having a person check each point and tell the camera which way to rotate, etc. But that, unfortunately, is beyond the capacity of a small project like this.

And we got 72 pictures for less than it would take a photographer to get a few! So we will tell the story with a map and a slideshow to bring home for our readers, listeners, and viewers the scale of the project.

Another sample pic

Another sample pic