Let’s Find Those Parcel Owners (Maps in R)

This is really intended as an introduction to the sf and leaflet packages in R. However, I will do so in the context of investigating public data sources to gather deed information for Reeves County in Texas (I guess I feel a little bad about excluding @Landmannery on my Twitter post about Skilling so I went landman-centric). And thanks to @LandmanLife for answering a few q’s.


Follow my blog


Package Install

Along with sf and leaflet, I will need to install downloader and tigris. The other packages should be installed courtesy of tidyverse.

install.packages(c('sf', 'leaflet', 'downloader', 'tigris'))

Get the data

While it’s not hard to get shapefiles of abstracts with a simple loop, getting parcel info is a little more difficult as it’s usually stored on the county level, and often in differing formats. Uber annoying.

Luckily, starting in 2019, the Texas Natural Resources Information System has been collecting this data. If we click on Reeves on the map, it should give us the ability to download a vector. But why go through that hassle? Let’s just get the link (right-click and copy) and download it automatically into R.

url1 <- 'https://data.tnris.org/2679b514-bb7b-409f-97f3-ee3879f34448/resources/stratmap19-landparcels_48389_vector.zip'

#Download file into R as new file called dataset.zip, unzip it, and then delete it
downloader::download(url1, dest = 'dataset.zip')
unzip('dataset.zip')
unlink('dataset.zip')

You will notice that it creates a new folder in your directory called shp. The shapefiles we want are there.


Read the file

Now, let’s create what is called an sf dataframe, which is essentially the shapefile data with a column that defines the shape. This allows us to do typical R data cleanup using tidyverse.

#Load data into R in sf dataframe called df
df <- sf::read_sf('./shp/stratmap19-landparcels_48389_reeves_201904.shp')

#Look at first few rows
head(df)

You will see this in the R console.

You can see a lot of information. The top portion shows location info. It also shows that this is a combination of polygons with XY coordinates. The bbox is the min and max coordinates of the data. The CRS is the coordinate system. There are also several additional columns that are hidden. To see them all, type:

library(dplyr)
head(df %>% data.frame())

We have information such as size of each parcel in acres, current owner, and their address. All info I will use.


Data Calculations

XY type coordinates generally make my brain hurt, so I look to convert to Lat/Longs. In this case I will change it to CRS 4326, which is WGS 84 in Lat/Long.

df <- sf::st_transform(df, crs = 4326)

I also want to create a column that defines information I want to display on the map when I click on a parcel. Now, this will be using a little bit of html, but it’s not as bad as you’d think. <b>Something</b> means bold it, while </br> means put in a new line. I will also be using glue from the tidyverse to create individualized strings.

df <- df %>% mutate(popup = glue::glue('<b>Owner: </b> {OWNER_NAME}<br>
                                       <b>Acres (Legal): </b> {LEGAL_AREA}<br>
                                       <b>Acres (Shapefile): </b> {GIS_AREA}<br>
                                       <b>Description: </b> {LEGAL_DESC}<br>
                                       <b>Address: </b> {MAIL_ADDR}<br>
                                       <b>Source: </b> {SOURCE}'))

And that should be enough. I can map it in leaflet. However, just to save some space, let’s first look at the owners with the most surface acreage to see if there’s a more interesting insight.


Data Investigation

We can use dplyr real quick to investigate the highest owners.

df %>% data.frame() %>%
  group_by(OWNER_NAME) %>%
  summarise(acres = sum(GIS_AREA)) %>%
  ungroup() %>%
  arrange(desc(acres))

Figure 1: Top Ten Surface Owners – Reeves County TX


Map

Texas Pacific Land Trust, one of the largest private land holders in Texas, comes in at the top of the list. So let’s just filter the data and see where the acreage position is.

df1 <- df %>% filter(grepl('TEXAS PACIFIC', OWNER_NAME))

I also need to pull in a Reeves county shapefile from the tigris package.

counties <- tigris::counties(state = 'TX')
counties <- st_as_sf(counties)
counties <- counties %>% select(County = NAME, geometry)
counties <- st_transform(counties, crs = 4326) %>%
                filter(County == 'Reeves')

And we can plot it up in Leaflet.

leaflet() %>% 
  addProviderTiles(providers$OpenStreetMap) %>%
  addPolygons(data = counties$geometry,
              fillColor = 'transparent', weight = 2) %>%
  addPolygons(data = df1$geometry, 
              popup = df1$popup, 
              fillColor = 'orange',
              fillOpacity = 0.25,
              color = 'black', weight = 1)

Figure 2: Texas Pacific Land Trust Deed Acreage

Strategic Mapping Program (StratMap). Land Parcels, 2019-03-01. Web. 2020-09-08.

Go ahead and click on any of the squares and you will see parcel data pop up.

Summary

And that’s it for this round. Hope you enjoyed it. If you see anything wrong or want me to look into something else, just leave me a comment. I’ll do the same for Texas pipelines soon as well.

Faux Out

4 thoughts on “Let’s Find Those Parcel Owners (Maps in R)”

  1. Thanks for the tutorial. I got it almost working. Having an issue with plotting the Reeves county polygon in the last step. Getting the error :
    Error in derivePolygons(data, lng, lat, missing(lng), missing(lat), “addPolygons”) : object ‘Reeves’ not found

    Any suggestions? I’m loading tigris and the other packages.
    _________

    library(tigris)
    library(leaflet)
    library(sf)

    counties <- tigris::counties(state = 'TX')
    counties <- st_as_sf(counties)
    counties % select(County = NAME, geometry)
    counties %
    filter(County == ‘Reeves’)

    leaflet() %>%
    addProviderTiles(providers$OpenStreetMap) %>%
    addPolygons(data = Reeves$geometry,
    fillColor = ‘transparent’, weight = 2) %>%
    addPolygons(data = df1$geometry,
    popup = df1$popup,
    fillColor = ‘orange’,
    fillOpacity = 0.25,
    color = ‘black’, weight = 1)

    #Error in derivePolygons(data, lng, lat, missing(lng), missing(lat), “addPolygons”) :
    #object ‘Reeves’ not found

    1. Hey Frac_This, looks like I made a mistake. Instead of Reeves$geometry, it should be counties$geometry. I made the update. Also, you should be piping and defining the new variables for counties.

      counties <- counties %>% select(County = NAME, geometry)
      counties <- counties %>%
      filter(County == ‘Reeves’)

      Thanks for reading!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: