Data Visualization

Go back to Homepage

Virginia, Age, and Income at a Glance

As a proud Virginian, I wanted to take advantage of the census data and map visualization tools I learned across my time in Reporting in the Digital Age to find if there were any trends between the median age and median income in counties across Virginia. I landed on using the mapping tools found in the MapView packages and used the census data to formulate a dynamic analysis of my subject matter. Enjoy!


Laying down the foundation

Before we go in to making our maps, we must first download all of the necessary packages in order to make the maps we desire. I made sure to bring the tmap and mapview packages over just to make sure I had multiple options for my map visualization.

knitr::opts_chunk$set(echo = TRUE)

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tigris)
To enable caching of data, set `options(tigris_use_cache = TRUE)`
in your R script or .Rprofile.
library(sf)
Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
library(tmap)
Breaking News: tmap 3.x is retiring. Please test v4, e.g. with
remotes::install_github('r-tmap/tmap')
library(tmaptools)
library(htmltools)
library(janitor)

Attaching package: 'janitor'

The following objects are masked from 'package:stats':

    chisq.test, fisher.test
library(rmapshaper)
library(here)
here() starts at /cloud/project
library(tidycensus)
library(mapview)
library(leafsync)
library(leaflet.extras2)
Loading required package: leaflet
options(tigris_class = "sf")

Next, I made sure to input the census API key in order to access the census data that I ultimately used to find the variables for my mapping, age and income.

# The census key for MapView mapping

census_api_key("2a6f8c21a30d3024e038d67d7d4eba647dc79cd4", overwrite=TRUE)
To install your API key for use in future sessions, run this function with `install = TRUE`.

Creating an Interactive County Census Map Visualization using MapView

I ultimately landed on using MapView in order to create a visually appealing map visualization that any consumer may be able to understand. To create the map, I followed the following steps and code in order to produce a map of Virginia demonstrating the median age and another comparing the median income of different counties in order to find any relation between age and income in Virginia.

# Establish the potential variables I want to use in the analysis of median age in Virginia counties.

myvars <- c(totalpop = "B01003_001",
            medincome = "B19013_001",
            medage = "B01002_001")
# Make a table with all of the variables chosen 

va_counties<- get_acs(geography = "county",
                       variables = c(myvars),
                       state = "VA",
                       output = "wide",
                       geometry = TRUE)
Getting data from the 2017-2021 5-year ACS
Downloading feature geometry from the Census website.  To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |                                                                      |   1%
  |                                                                            
  |=                                                                     |   1%
  |                                                                            
  |=                                                                     |   2%
  |                                                                            
  |==                                                                    |   2%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |===                                                                   |   4%
  |                                                                            
  |===                                                                   |   5%
  |                                                                            
  |====                                                                  |   5%
  |                                                                            
  |====                                                                  |   6%
  |                                                                            
  |=====                                                                 |   7%
  |                                                                            
  |======                                                                |   8%
  |                                                                            
  |======                                                                |   9%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |=======                                                               |  11%
  |                                                                            
  |========                                                              |  11%
  |                                                                            
  |========                                                              |  12%
  |                                                                            
  |=========                                                             |  12%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |===========                                                           |  16%
  |                                                                            
  |================                                                      |  23%
  |                                                                            
  |=====================                                                 |  30%
  |                                                                            
  |==========================                                            |  37%
  |                                                                            
  |===============================                                       |  44%
  |                                                                            
  |====================================                                  |  52%
  |                                                                            
  |=========================================                             |  59%
  |                                                                            
  |==============================================                        |  66%
  |                                                                            
  |================================================                      |  68%
  |                                                                            
  |=====================================================                 |  76%
  |                                                                            
  |==========================================================            |  83%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%
# Clean up the column names by taking out the "E"

colnames(va_counties) <- sub("E$", "", colnames(va_counties))

# Customize the labels and popups for the map by creating multiple labels for each map and a common-use popup

mylabelone <- glue::glue("{va_counties$NAM}: {va_counties$medage} years old")
mylabeltwo <- glue::glue("{va_counties$NAM}: ${va_counties$medincome}")

mypopup <- glue::glue("<strong>{va_counties$NAM}</strong><br />
                      Total Population: {va_counties$totalpop}<br />
                      Median Age in the County: {va_counties$medage}<br />
                      Median Income in the County: ${va_counties$medincome}") %>% 
  lapply(htmltools::HTML)

# Write the code and put in a color scheme that I want to create the final interactive maps of both age and income, split between blue to demonstrate income and pink to demonstrate age.

vamap_age <- mapview(va_counties, zcol = "medage", 
         col.regions = RColorBrewer::brewer.pal(9, "PuRd"), 
         alpha.regions = 1,
         popup = mypopup,
        label = mylabelone)
Warning: Found less unique colors (9) than unique zcol values (94)! 
Interpolating color vector to match number of zcol values.
vamap_income <- mapview(va_counties, zcol = "medincome", 
         col.regions = RColorBrewer::brewer.pal(9, "Blues"), 
         alpha.regions = 1,
         popup = mypopup,
        label = mylabeltwo)
Warning: Found less unique colors (9) than unique zcol values (133)! 
Interpolating color vector to match number of zcol values.
sync(vamap_income, vamap_age)
vamap_age | vamap_income

Conclusions

Using the map visualization and census data, one can find that the county with the highest median income in Virginia is Northumberland County with a median age of 59.8. The county with the lowest median age was Lexington City County with a median age of 22.4, probably due to the dense college-age population in the area. In income, however, the county with the highest median income was Loudoun County with a median income of 156,821 dollars and the lowest was Dickenson County at 33,905 dollars. Virginia displays an interesting trend with income and age, in that it shows a more bell-curved trend rather than a positive or negative correlation between income and age. In Virginia being my home state, I find this pattern to be quite indicative of the city-sprawling areas in the state, but question the role that older retirees and their incomes have in skewing the results of this data collection.