library(tidyverse)
library(tidyr)
library(leaflet)
cities500 <- read_csv("500CitiesLocalHealthIndicators.cdc.csv")
data(cities500)Healthy Cities GIS Assignment
Load the libraries and set the working directory
The GeoLocation variable has (lat, long) format
Split GeoLocation (lat, long) into two columns: lat and long
latlong <- cities500|>
mutate(GeoLocation = str_replace_all(GeoLocation, "[()]", ""))|>
separate(GeoLocation, into = c("lat", "long"), sep = ",", convert = TRUE)
head(latlong)# A tibble: 6 × 25
Year StateAbbr StateDesc CityName GeographicLevel DataSource Category
<dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 2017 CA California Hawthorne Census Tract BRFSS Health Outcom…
2 2017 CA California Hawthorne City BRFSS Unhealthy Beh…
3 2017 CA California Hayward City BRFSS Health Outcom…
4 2017 CA California Hayward City BRFSS Unhealthy Beh…
5 2017 CA California Hemet City BRFSS Prevention
6 2017 CA California Indio Census Tract BRFSS Health Outcom…
# ℹ 18 more variables: UniqueID <chr>, Measure <chr>, Data_Value_Unit <chr>,
# DataValueTypeID <chr>, Data_Value_Type <chr>, Data_Value <dbl>,
# Low_Confidence_Limit <dbl>, High_Confidence_Limit <dbl>,
# Data_Value_Footnote_Symbol <chr>, Data_Value_Footnote <chr>,
# PopulationCount <dbl>, lat <dbl>, long <dbl>, CategoryID <chr>,
# MeasureId <chr>, CityFIPS <dbl>, TractFIPS <dbl>, Short_Question_Text <chr>
Filter the dataset
Remove the StateDesc that includes the United Sates, select Prevention as the category (of interest), filter for only measuring crude prevalence and select only 2017.
latlong_clean <- latlong |>
filter(StateDesc != "United States") |>
filter(Data_Value_Type == "Crude prevalence") |>
filter(Year == 2017) |>
filter(StateAbbr == "CT") |>
filter(Category == "Unhealthy Behaviors")
head(latlong_clean)# A tibble: 6 × 25
Year StateAbbr StateDesc CityName GeographicLevel DataSource Category
<dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 2017 CT Connecticut Bridgeport Census Tract BRFSS Unhealthy B…
2 2017 CT Connecticut Danbury City BRFSS Unhealthy B…
3 2017 CT Connecticut Norwalk Census Tract BRFSS Unhealthy B…
4 2017 CT Connecticut Bridgeport Census Tract BRFSS Unhealthy B…
5 2017 CT Connecticut Hartford Census Tract BRFSS Unhealthy B…
6 2017 CT Connecticut Waterbury Census Tract BRFSS Unhealthy B…
# ℹ 18 more variables: UniqueID <chr>, Measure <chr>, Data_Value_Unit <chr>,
# DataValueTypeID <chr>, Data_Value_Type <chr>, Data_Value <dbl>,
# Low_Confidence_Limit <dbl>, High_Confidence_Limit <dbl>,
# Data_Value_Footnote_Symbol <chr>, Data_Value_Footnote <chr>,
# PopulationCount <dbl>, lat <dbl>, long <dbl>, CategoryID <chr>,
# MeasureId <chr>, CityFIPS <dbl>, TractFIPS <dbl>, Short_Question_Text <chr>
What variables are included? (can any of them be removed?)
names(latlong_clean) [1] "Year" "StateAbbr"
[3] "StateDesc" "CityName"
[5] "GeographicLevel" "DataSource"
[7] "Category" "UniqueID"
[9] "Measure" "Data_Value_Unit"
[11] "DataValueTypeID" "Data_Value_Type"
[13] "Data_Value" "Low_Confidence_Limit"
[15] "High_Confidence_Limit" "Data_Value_Footnote_Symbol"
[17] "Data_Value_Footnote" "PopulationCount"
[19] "lat" "long"
[21] "CategoryID" "MeasureId"
[23] "CityFIPS" "TractFIPS"
[25] "Short_Question_Text"
Remove the variables that will not be used in the assignment
latlong_clean2 <- latlong_clean |>
select(-DataSource,-Data_Value_Unit, -DataValueTypeID, -Low_Confidence_Limit, -High_Confidence_Limit, -Data_Value_Footnote_Symbol, -Data_Value_Footnote)
head(latlong_clean2)# A tibble: 6 × 18
Year StateAbbr StateDesc CityName GeographicLevel Category UniqueID Measure
<dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 2017 CT Connecticut Bridgep… Census Tract Unhealt… 0908000… Obesit…
2 2017 CT Connecticut Danbury City Unhealt… 918430 Obesit…
3 2017 CT Connecticut Norwalk Census Tract Unhealt… 0955990… Obesit…
4 2017 CT Connecticut Bridgep… Census Tract Unhealt… 0908000… Curren…
5 2017 CT Connecticut Hartford Census Tract Unhealt… 0937000… Obesit…
6 2017 CT Connecticut Waterbu… Census Tract Unhealt… 0980000… Obesit…
# ℹ 10 more variables: Data_Value_Type <chr>, Data_Value <dbl>,
# PopulationCount <dbl>, lat <dbl>, long <dbl>, CategoryID <chr>,
# MeasureId <chr>, CityFIPS <dbl>, TractFIPS <dbl>, Short_Question_Text <chr>
The new dataset “Prevention” is a manageable dataset now.
For your assignment, work with a cleaned dataset.
1. Once you run the above code and learn how to filter this complicated dataset, perform your own investigation by filtering this dataset however you choose so that you have a subset with no more than 900 observations.
Filter chunk here (you may need multiple chunks)
latlong_MD_Diabetes <- latlong |> filter (StateAbbr == "MD", GeographicLevel == "Census Tract",
Year == 2017,
Data_Value_Type == "Crude prevalence",
Category == "Health Outcomes",
Measure == "Diagnosed diabetes among adults aged >=18 Years", !is.na(Data_Value))
head(latlong_MD_Diabetes)# A tibble: 6 × 25
Year StateAbbr StateDesc CityName GeographicLevel DataSource Category
<dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 2017 MD Maryland Baltimore Census Tract BRFSS Health Outcomes
2 2017 MD Maryland Baltimore Census Tract BRFSS Health Outcomes
3 2017 MD Maryland Baltimore Census Tract BRFSS Health Outcomes
4 2017 MD Maryland Baltimore Census Tract BRFSS Health Outcomes
5 2017 MD Maryland Baltimore Census Tract BRFSS Health Outcomes
6 2017 MD Maryland Baltimore Census Tract BRFSS Health Outcomes
# ℹ 18 more variables: UniqueID <chr>, Measure <chr>, Data_Value_Unit <chr>,
# DataValueTypeID <chr>, Data_Value_Type <chr>, Data_Value <dbl>,
# Low_Confidence_Limit <dbl>, High_Confidence_Limit <dbl>,
# Data_Value_Footnote_Symbol <chr>, Data_Value_Footnote <chr>,
# PopulationCount <dbl>, lat <dbl>, long <dbl>, CategoryID <chr>,
# MeasureId <chr>, CityFIPS <dbl>, TractFIPS <dbl>, Short_Question_Text <chr>
Created a dataset called “Latlong_MD_Diabetes” that contains Maryland specific data for diagnosed diatetes among adults aged >=18 years without na values. All Maryland Data is from Baltimore, 2017.
latlong_MD_Diabetes <- latlong_MD_Diabetes |> select(-DataSource,-Data_Value_Unit, -DataValueTypeID, -Low_Confidence_Limit, -High_Confidence_Limit, -Data_Value_Footnote_Symbol, -Data_Value_Footnote)
nrow(latlong_MD_Diabetes)[1] 199
Removed unused variables(Which isn’t really necessary) and checks observation count(199 observations)
2. Based on the GIS tutorial (Japan earthquakes), create one plot about something in your subsetted dataset.
First plot chunk here
ggplot(latlong_MD_Diabetes, aes(x = Data_Value)) +
geom_histogram(binwidth = 2, fill = "red", color = "white") +
theme_classic() +
labs( title = "Adult Diabetes Prevalence MD Census Tracts, 2017", x = "Crude Adult Diabetes Prevalence (%)", y = "Number of Census Tracts", caption = "Source: CDC 500 Cities Project")This is a histogram showing the number of census tracts(defined geographical areas, in my case: Baltimore, MD) that fall into specific bins for crude adult prevalence rate of diabetes. Each bin is 2% percentage points wide.
3. Now create a map of your subsetted dataset.
First map chunk here
diabetes_pal <- colorNumeric(palette = "Reds", domain = latlong_MD_Diabetes$Data_Value)
leaflet(latlong_MD_Diabetes) |> setView( lng = -76.61, lat = 39.29, zoom = 11) |> addTiles() |>
addCircleMarkers(lng = ~long, lat = ~lat, radius = 6, color = ~diabetes_pal(Data_Value), fillColor = ~diabetes_pal(Data_Value), fillOpacity = 0.7, stroke = FALSE) |>
addLegend( position = "bottomright", pal = diabetes_pal, values = ~Data_Value, title = "Diabetes Prevalence (%)"
)This interactive map displays the estimated crude prevalence of diagnosed diabetes among adults for census tracts in Baltimore, Maryland. Each circle represents a census tract. Darker red circles indicate census tracts with higher estimated diabetes prevalence. The leaflet plot is set to central baltimore at approximately city level resolution/scale. Uses a red color scale for diabetes prevalence in both the legend and circles representing each census tract. Using addTiles(), Adds a real background map of baltimore to plot the lat. and long. of each census tract, represented by the circles. Stroke= false removes the background border for each circle.The legend is positioned towards the bottom right corner as I felt that made most sense visually to maximize readability of the map. Created a color scale for the continous variable, Data_value, which contains crude diabetes prevalence rate values, using colorNumeric. The color palette is set to red.
4. Refine your map to include a mouse-click tooltip
Refined map chunk here
leaflet(latlong_MD_Diabetes) |> setView( lng = -76.61, lat = 39.29, zoom = 11) |> addTiles() |>
addCircleMarkers( lng = ~long,lat = ~lat, radius = 6, color = ~diabetes_pal(Data_Value), fillColor = ~diabetes_pal(Data_Value), fillOpacity = 0.7, stroke = FALSE,
popup = ~paste0( "<b>Census Tract:</b> ", TractFIPS, "<br><b>Diabetes Prevalence:</b> ", Data_Value, "%","<br><b>Population:</b> ", PopulationCount)) |>
addLegend( position = "bottomright", pal = diabetes_pal, values = ~Data_Value, title = "Diabetes Prevalence (%)")5. Write a paragraph
In a paragraph, describe the plots you created and what they show.
The Leaflet maps show the geographic distribution of estimated adult diabetes prevalence from census tracts in Baltimore, Maryland, in 2017. Each circle represents a census tract and is positioned using the latitude and longitude associated with each tract. The color of each circle represents the crude prevalence of diagnosed diabetes among adults age 18 and older. The darker the red indicating higher estimated prevalence and the lighter the red indicating lower prevalence. The refined map using the popup argument also allows the user to click on each circle to view its census tract’s FIPS code, estimated diabetes prevalence, and population count. Overall, the maps make it easier to see how diabetes prevalence varies geographically across different parts of Baltimore, especially when compared to a histogram, which can not physical show on a map where each census tract is and its diabetes prevalence found there.