The potential audience for this map includes all residents of the Portland-Metro area. The map assumes some a priori familiarity with the layout of the city, the rivers, and the neighborhood boundaries. The discrete color scaling is slightly more complex than is typical for similar maps, so there is also some presumption of literacy with regard to deciphering the density ranges in the legend.
Graph Type
This figure is a chloropleth map, which uses color filling or shading to represent quantitative information about specific geographic areas (in this case, neighborhoods). More uniquely, this map uses discrete color scaling, which means continuous numeric values (i.e., renter population density) are mapped to discrete categories that are represented by predefined colors on the map. An alternative approach to shading is to use a continuous color scale, although this approach can sometimes make it difficult to compare similar numeric values.
Representation Description
Darker colors show that there are higher densities of renters in neighborhoods spanning the downtown and inner-NW portions of the city, as well as the inner-east side. The figure legend tells us that these areas have as many as 2,180 renters per square kilometer. On the other hand, lighter colors in indicate lower renter densities, though some of these areas are large and include places like Forest Park, where there is little to no housing in general. Note that these areas might have fewer than 5 renters per square kilometer. In general, we expect that renter densities will somewhat mirror overall population densities. Finally, we notice that there are some gaps in the map, including at the airport and the unclaimed industrial district along the west bank of the Willamette, north of downtown.
Tips for Interpretation
Assuming you are somewhat familiar with the layout of the city of Portland, make sure to orient yourself properly. North is up; west is left; etc. The Willamette River runs vertically up the center of the map before joining the Columbia north of the city. Latitude and longitude values are marked along the left and bottom borders of the figure.
Colors on the map represent renter population density by neighborhood. Look for darker colors to see where there are more renters per square kilometer. Lighter colors will illustrate fewer renters per square kilometer, and white/colorless neighborhoods are missing data entirely. Take note of the legend values that associate specific colors with set ranges of renter densities. Be careful to differentiate small numbers with decimals (e.g., 4.322) from larger values with similar numbers of digits (e.g., 1,628).
Presentation Considerations
It is vital with chloropleth maps to make sure quantitative information is somehow corrected for geographic area, otherwise it is difficult to compare regions of differing sizes. It is for this reason that our map uses renter population density, rather than total number of renters.
For color aesthetics, we used an appropriate shade of blue for the river bodies, since it makes the map more intuitive to all audiences. Discrete shades of red were used to fill in neighborhoods against a white background, since they were clearly distinct from the blue rivers, and because this approach increases visibility of the missing data regions. Rather than use a continuous color scale, which can make it difficult to compare similar values (e.g., what does a 10 person/km^2 change in red even look like?), a discrete color scale was used instead, which created “bins” for ranges of values. This approach decreases the number of colors in the map, but helps to increase comparison between artificially created levels of the renter density variable. To find the best cutoffs between these color categories, we used Jenks’s method, which determines natural and effective value boundaries.
Method
Data preparation is slightly more complex in this instance. One needs to load in the shapefiles for the neighborhoods and rivers, access a subset of the census data, fix neighborhood labels to be consistent between data frames, and then join all of this information together. Afterwards, it will be possible to calculate population densities using shapefile area information.
Code
# Data prep## Load the neighborhood boundariespdx_boundaries <-st_read(here("data","Neighborhoods__Regions_-shp" ))## Load the river boundariesriver_boundaries <-st_read(here("data","Willamette_Columbia_River_Ordinary_High_Water-shp" )) |># Adjust resolutionst_simplify(dTolerance =10 )# Read in the neighborhoods and renter populations separately,# then we can join them togetherpdx_population <-read_excel(here("data","Census_2010_Data_Cleanedup.xlsx"),sheet="Census_2010_Neighborhoods", range="A7:A101", col_names ="Neighborhood") |>mutate(Neighborhood=as.factor(Neighborhood))pdx_rent <-read_excel(here("data","Census_2010_Data_Cleanedup.xlsx"),sheet="Census_2010_Neighborhoods", range="CU7:CU101", col_names ="Renter.Pop")pdx_population <-cbind(pdx_population, pdx_rent)# "Manually" clean up the neighborhood labelspdx_population <- pdx_population |>mutate(Neighborhood=recode(Neighborhood,"ARGAY"="ARGAY TERRACE","BROOKLYN"="BROOKLYN ACTION CORPS","BUCKMAN"="BUCKMAN COMMUNITY ASSOCIATION","CENTENNIAL"="CENTENNIAL COMMUNITY ASSOCIATION","CULLY"="CULLY ASSOCIATION OF NEIGHBORS","CENTENNIAL"="CENTENNIAL COMMUNITY ASSOCIATION","DOWNTOWN"="PORTLAND DOWNTOWN","GOOSE HOLLOW"="GOOSE HOLLOW FOOTHILLS LEAGUE","HAYDEN ISLAND"="HAYDEN ISLAND NEIGHBORHOOD NETWORK","HOSFORD-ABERNETHY"="HOSFORD-ABERNETHY NEIGHBORHOOD DISTRICT ASSN.","IRVINGTON"="IRVINGTON COMMUNITY ASSOCIATION","LLOYD DISTRICT"="LLOYD DISTRICT COMMUNITY ASSOCIATION","NORTHWEST DISTRICT"="NORTHWEST DISTRICT ASSOCIATION","OLD TOWN-CHINATOWN"="OLD TOWN COMMUNITY ASSOCIATION","PARKROSE HEIGHTS"="PARKROSE HEIGHTS ASSOCIATION OF NEIGHBORS","PEARL"="PEARL DISTRICT","SABIN"="SABIN COMMUNITY ASSOCIATION","SELLWOOD-MORELAND"="SELLWOOD-MORELAND IMPROVEMENT LEAGUE","SOUTHWEST HILLS"="SOUTHWEST HILLS RESIDENTIAL LEAGUE","SUMNER"="SUMNER ASSOCIATION OF NEIGHBORS","SUNDERLAND"="SUNDERLAND ASSOCIATION OF NEIGHBORS","WILKES"="WILKES COMMUNITY GROUP"))# Left join renter population data with the boundary data setboundaries_with_pop <-left_join(pdx_boundaries, pdx_population, by=c("NAME"="Neighborhood"))# Calculate renter population densityboundaries_with_pop <- boundaries_with_pop |>mutate(adj_renter_pop = (Renter.Pop / (Shape_Area/1E6)) ) |>arrange(adj_renter_pop)
Next, it’s necessary to calculate the desired color quantiles using Jenks’s adaptive algorithm, which determines the most effective boundaries for the color categories.