TidyTuesday Week 27: Historical Markers

R
TidyTuesday
R-code
data visualization
sf
leaflet
TidyTuesday: Interactive Map of Arlington Historic Markers
Author
Published

July 4, 2023

Modified

November 3, 2023

Today’s TidyTuesday is about historical markers with the data coming from the Historical Marker Database. I’m going to add to the map that I made last week with information about Historic Districts in Arlington, VA. I’m going to make an interactive leaflet map with the new information added to the old map.

Loading libraries.

library(tidyverse) # who doesn't want to be tidy
library(leaflet) # interactive mapping
library(mapview) # simple interactive mapping
library(sf) # geocoding objects
library(openxlsx) # importing excel files from a URL

I’m not going to loading the no markers data, because I know I’m not going to use it.

tuesdata <- tidytuesdayR::tt_load(2023, week = 27)
--- Compiling #TidyTuesday Information for 2023-07-04 ----
--- There are 2 files available ---
--- Starting Download ---

    Downloading file 1 of 2: `historical_markers.csv`
    Downloading file 2 of 2: `no_markers.csv`
--- Download complete ---
historical_markers <- tuesdata$`historical_markers`
#no_markers <- tuesdata$`no_markers`

The data isn’t very clean. The website might want to consider drop-down menus for some of the bigger groups. Here’s an illustration look at some of many ways people rendered “Kentucky Historical Society and Kentucky Department of Highways”.

historical_markers %>% filter(state_or_prov == "Kentucky") %>% 
  group_by(erected_by) %>% count(sort = TRUE) %>% filter(n > 50)
# A tibble: 10 × 2
# Groups:   erected_by [10]
   erected_by                                                                n
   <chr>                                                                 <int>
 1 Kentucky Historical Society and Kentucky Department of Highways         634
 2 Kentucky Historical Society, Kentucky Department of Highways            165
 3 Kentucky Historical Society & Kentucky Department of Highways           159
 4 Kentucky Historical Society, Kentucky Department of Highways.           141
 5 the Kentucky Historical Society, Kentucky Department of Highways.        81
 6 Kentucky Historical Society-Kentucky Department of Highways              79
 7 Kentucky Department of Highways                                          75
 8 Kentucky Historical Society • Kentucky Department of Highways            65
 9 Kentucky Historical Society and Kentucky Department of Transportation    57
10 James Harrod Trust                                                       53

Filtering for Virginia only. I could filter by county == "Arlington County" also, but I actually want to get some of the adjacent markers, because I know there are some right on the county line and I’m not sure which jurisdiction they will fall in.

virginia_markers <- historical_markers %>% filter(state_or_prov == "Virginia") 

I’m going to load in my data from the previous visualization. The blog post on how I created these objects is here.

historic_4269 <- st_read("points.shp")
arlington_polygons_sf <- st_read("polygons.shp")

Now I’m adding html tags and transforming the coordinate system. More about that here.

# turn the url to HTML anchor tag
historic_4269 <- historic_4269 %>% 
  mutate(tag = paste0("More Info: <a href=", Extrn_L,">", Extrn_L, "</a>"))

#transforming crs
historic_4326 <- sf::st_transform(historic_4269, crs = 4326)
arlington_polygons_sf_4326 <- sf::st_transform(arlington_polygons_sf, crs = 4326) 

Now I’m roughly sub-setting to Arlington based on latitude and longitude.

va_markers_nova <-
  virginia_markers %>% filter(longitude_minus_w < -76.5 &
                                longitude_minus_w > -77.25) %>%
  filter(latitude_minus_s > 38.8 &
           latitude_minus_s < 39.4)

I know there is a lot of variation in the erected_by data (as seen for KY), so I’m going to check that out for this sub-set.

va_markers_nova %>% group_by(erected_by) %>% count(sort = TRUE)
# A tibble: 13 × 2
# Groups:   erected_by [13]
   erected_by                                                                  n
   <chr>                                                                   <int>
 1 Department of Historic Resources                                           34
 2 Arlington County, Virginia                                                 22
 3 Arlington County Virginia                                                   4
 4 Arlington County                                                            3
 5 Conservation & Development Commission                                       3
 6 Virginia Historic Landmarks Commission                                      3
 7 City of Alexandria                                                          1
 8 Continental Chapter, Daughters of the American Revolution                   1
 9 The Washington Society of Alexandria, U.S. Dept. of the Interior            1
10 Virginia Conservation Commission                                            1
11 Virginia Department of Historic Resources                                   1
12 Washington-Lee Society, Children of the American Revolution; Thomas Ne…     1
13 William G. Pomeroy Foundation                                               1

Change all the Arlington stuff to Arlington County. The Conservation & Development Comission and the Virginia Conservation Commission are the same entity- the name changed over the years. I’m adding the years to those entries. I suspect they and the Virginia Landmarks Commission are all now replaced by the Virginia Department of Historic Resources, but I couldn’t find a source for that.

va_markers_nova <- va_markers_nova %>%
  mutate(erected_by_clean = ifelse(
    str_detect(erected_by, "Arlington County"),
    "Arlington County",
    erected_by
  )) %>%
  mutate(
    erected_by_clean = ifelse(
      str_detect(erected_by_clean, "Historic Resources"),
      "Virginia Dept. of Historic Resources",
      erected_by_clean
    )
  ) %>%
  mutate(
    erected_by_clean = ifelse(
      str_detect(erected_by_clean, "Conservation &"),
      "Virginia Conservation & Development Commission (1926- 1938)",
      erected_by_clean
    )) %>%
  mutate(
    erected_by_clean = ifelse(
      str_detect(erected_by_clean, "Virginia Conservation Commission"),
      "Virginia Conservation Commission (1938-1948)",
      erected_by_clean
    ))

Checking our cleaned list.

va_markers_nova %>% group_by(erected_by_clean) %>% count(sort = TRUE)
# A tibble: 10 × 2
# Groups:   erected_by_clean [10]
   erected_by_clean                                                            n
   <chr>                                                                   <int>
 1 Virginia Dept. of Historic Resources                                       35
 2 Arlington County                                                           29
 3 Virginia Conservation & Development Commission (1926- 1938)                 3
 4 Virginia Historic Landmarks Commission                                      3
 5 City of Alexandria                                                          1
 6 Continental Chapter, Daughters of the American Revolution                   1
 7 The Washington Society of Alexandria, U.S. Dept. of the Interior            1
 8 Virginia Conservation Commission (1938-1948)                                1
 9 Washington-Lee Society, Children of the American Revolution; Thomas Ne…     1
10 William G. Pomeroy Foundation                                               1

Converting this to a sf object. For more information about that, see my last week’s TidyTuesday. Just take a quick look to make sure I’m happy. The mapview package is great for quick and dirty maps; I’ll use leaflet to make the fancy one.

va_markers_nova_geo <- st_as_sf(va_markers_nova, coords = c(9, 8), crs = 4326)

mapview(va_markers_nova_geo) + mapview(historic_4326) + mapview(arlington_polygons_sf_4326)

Making the HTML anchor tag for my pop-up with a live link. This is covered in my leaflet revision to last week’s TidyTuesday.

# turn the url to HTML anchor tag
va_markers_nova_geo <- va_markers_nova_geo %>% 
  mutate(tag = paste0("More Info: <a href=", link,">", link, "</a>"))

A first view of the map.

pal <- colorFactor(palette = "viridis", domain = arlington_polygons_sf_4326$CIVIC)

leaflet_map <- leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(
    data = arlington_polygons_sf_4326,
    weight = 1,
    label = ~ CIVIC,
    color = ~ pal(CIVIC), 
    group = "Arlington Neighborhoods"
  ) %>%
  addCircleMarkers(
    data = historic_4326,
    popup = ~ paste0("<b>", Prprt_N, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "black",
    stroke = NA,
    group = "Historic Neighborhoods"
  ) %>% 
    addCircleMarkers(
    data = va_markers_nova_geo,
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "red",
    stroke = NA,
    group = "Historic Markers")
  
leaflet_map

Now I’m going to subset the point data into data that is within the Arlington polygons and that which is outside the boundaries. I found a nice explanation on the GIS Stack Exchange on how to use st_intersects() for this.

Basically, I find the interections between the two geometry datasets. If there isn’t one, the length of the list will be 0. Using sapply, we can create a TRUE/FALSE vector when we test against the condition of length == 0.

intersection <-
  st_intersects(va_markers_nova_geo, arlington_polygons_sf_4326)
b <-
  sapply(st_intersects(va_markers_nova_geo, arlington_polygons_sf_4326), function(x) {
    length(x) == 0
  })

So, now I subset the original marker data into Arlington and not Arlington.

markers_arlington <- va_markers_nova_geo[!b, ]
markers_not_arlington <- va_markers_nova_geo[b, ]

And then map this. I put in a layer control so you can remove layers.

leaflet_map <- leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(
    data = arlington_polygons_sf_4326,
    weight = 1,
    label = ~ CIVIC,
    color = ~ pal(CIVIC),
    group = "Arlington Neighborhoods"
  ) %>%
  addCircleMarkers(
    data = historic_4326,
    label = ~ Prprt_N,
    popup = ~ paste0("<b>", Prprt_N, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "black",
    group = "Historic Neighborhoods",
    stroke = NA
  ) %>%
  addCircleMarkers(
    data = markers_arlington,
    label = ~ title,
    popup = ~ paste0("<b>", title, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "red",
    stroke = NA,
    group = "Historic Markers in Arlington"
  ) %>%
  addCircleMarkers(
    data = markers_not_arlington,
    label = ~ title,
    popup = ~ paste0("<b>", title, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "blue",
    stroke = NA,
    group = "Historic Markers not in Arlington"
  ) %>%
  addLayersControl(
    #baseGroups = c("CartoDB.Positron"),
    overlayGroups = c(
      "Arlington Neighborhoods",
      "Historic Neighborhoods",
      "Historic Markers",
      "Historic Markers not in Arlington"
    ),
    options = layersControlOptions(collapsed = FALSE)
  )
leaflet_map

Several markers are on the county boundary and some do fall outside the county, such as those at Washington Reagan Airport.

None of Arlington’s historic neighborhood districts show up. According to the markers page, “A second exception in these guidelines are National Register of Historic Places and other officially sanctioned brass tablets that simply name the historic building or site. They can only anchor a marker page when there is no other qualifying marker nearby. When there is one, it should be used to further illustrate that other marker’s page.” So, as I understand it, there should be entries.

Many of the Historic Marker’s are related to the defense of Washington, DC during the American Civil War. I made a list manually from Wikipedia, and added a column labeling these “civil war defense”.

fort <- read.xlsx(here::here("posts/2023-07-04-tidytuesday-historic-markers", "forts2.xlsx"), sheet = 1)

I’m going to use a join to determine if a marker is a civil war defense fort. If it matches, there will be an entry in the column Defense_Label that says “Civil War Defense”. If there isn’t a match, there will be an NA. Using a left join with markers_arlington keeps all of the entries.

markers_arlington <-
  markers_arlington %>% left_join(fort, by = c("title" = "Fort_Name"))

Now making a TRUE/FALSE column to subset on. If the Defense_Label is NA, then we know it does not match with a fort, so I set the label to FALSE. Otherwise, TRUE.

Civil_war <- markers_arlington %>%
  mutate(Defense_Label = ifelse(is.na(Defense_Label), FALSE, TRUE))

Now create the two groups by using this TRUE/FALSE column to index on.

markers_arlington_cw <- Civil_war[Civil_war$Defense_Label , ]
markers_arlington_other <- Civil_war[!Civil_war$Defense_Label , ]

Now add these new groups to the map and remove the old historic markers group.

leaflet_map <- leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(
    data = arlington_polygons_sf_4326,
    weight = 1,
    label = ~ CIVIC,
    color = ~ pal(CIVIC),
    group = "Arlington Neighborhoods"
  ) %>%
  addCircleMarkers(
    data = historic_4326,
    label = ~ Prprt_N,
    popup = ~ paste0("<b>", Prprt_N, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "black",
    group = "Arlington Historic Neighborhoods",
    stroke = NA
  ) %>%
  addCircleMarkers(
    data = markers_arlington_cw,
    label = ~ title,
    popup = ~ paste0("<b>", title, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "red",
    stroke = NA,
    group = "Civil War Federal Defense Historic Markers"
  ) %>%
  
  addCircleMarkers(
    data = markers_arlington_other,
    label = ~ title,
    popup = ~ paste0("<b>", title, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "green",
    stroke = NA,
    group = "Arlington Historic Markers"
  ) %>%
  addCircleMarkers(
    data = markers_not_arlington,
    label = ~ title,
    popup = ~ paste0("<b>", title, "</b>", "<br>", tag),
    # note the tilde notation!
    opacity = 1,
    radius = 7,
    color = "blue",
    stroke = NA,
    group = "Historic Markers not in Arlington"
  ) %>%
  addLayersControl(
    #baseGroups = c("CartoDB.Positron"),
    overlayGroups = c(
      "Arlington Neighborhoods",
      "Arlington Historic Neighborhoods",
      "Arlington Historic Markers",
      "Civil War Federal Defense Historic Markers" ,
      "Historic Markers not in Arlington"
    ),
    options = layersControlOptions(collapsed = FALSE)
  )
leaflet_map

And there we have it. A lovely map with different types of local historic features.

Citation

BibTeX citation:
@online{sinks2023,
  author = {Sinks, Louise E.},
  title = {TidyTuesday {Week} 27: {Historical} {Markers}},
  date = {2023-07-04},
  url = {https://lsinks.github.io/posts/2023-07-04-historic-markers/markers.html},
  langid = {en}
}
For attribution, please cite this work as:
Sinks, Louise E. 2023. “TidyTuesday Week 27: Historical Markers.” July 4, 2023. https://lsinks.github.io/posts/2023-07-04-historic-markers/markers.html.