Public
Edited
Apr 2, 2024
Insert cell
md`# Graduated Symbol Mapping
People with a bachelor's degree within the state of Maryland
\nGEOG 3540 - Brianna Haynes


The map below displays the state of Maryland and the amount of people in each county that have a bachelor's degree. I chose this variable because I wanted to see if there was any kind of pattern about where people with bachelor's degrees live in Maryland. While there seems to be a slight clustering around the middle of Maryland, that area is also where several universities are located, so it makes sense that those places would be higher. Besides that, there is no clear pattern that I can make out. `
Insert cell
Insert cell
graduatedSymbols = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
svg.append("path")
.datum(topojson.feature(basepolygons, basepolygons.objects.MarylandQGIS))
.attr("fill", "grey") //Changes the colors of the basemap.
.attr("d", path_basemap);
svg.append("path")
.datum(topojson.mesh(basepolygons, basepolygons.objects.MarylandQGIS, (a, b) => a !== b))
.attr("fill", "none")
.attr("stroke", "white") //Changes the color of the county borders.
.attr("stroke-linejoin", "round")
.attr("d", path_basemap);
svg.append("g")
.selectAll("circle")
.data(points.features
.map(d => (d.value = Math.sqrt(d.properties[attributeName]), d))
.sort((a, b) => b.value - a.value))
.join("circle")
.attr("transform", d => `translate(${path_points.centroid(d)})`)
.attr("r", d => radius(d.value))
.attr("fill", d => colors(d.value))
.attr("fill-opacity", 1)
//Controls the opacity of the point circles on the map.
.attr("stroke", "Black")
//Controls the outline of the point circles on the map.
.attr("stroke-width", 0.5)
//Controls the thickness of the outline around the point circles on the map.
.append("title")
.text(d => `${d.properties[idName]} : ${format(d.properties[attributeName])}`);
//This line of code is responsible for displaying a textbox with the appropriate information when a mouse is hovered over the map. The textbox will display the value associated with the connected idName function (which is the name of the county in this case) followed by the value connected to that county, assigned by the attributeName.
return svg.node();
}
Insert cell
symbolLegendDef = {
return {
type: "symbol",
title: "People with Bachelor's Degrees",
fill: "symbolColor",
size: "symbolSize",
direction: 'Horizontal',
columns: undefined,
rowPadding: 10,
columnPadding: 10,
clipHeight: undefined,
titleOrient: 'Top',
symbolStrokeColor: '#000',
symbolStrokeWidth: 0.5
// This block of code is responsible for the position of the legend in relation to the map. The title, color of the title, and the outline of the circles in the legend can all be changed here.
};
}
Insert cell
height = 500
Insert cell
width = 975
Insert cell
path_points = d3.geoPath().projection(projection)
Insert cell
path_basemap = d3.geoPath().projection(projection)
Insert cell
projection = d3.geoTransverseMercator().rotate([78,0]).fitExtent([[80, 80], [width, height]], basefeatures);
//This is how the map will be projected. It can also be rotated so that it best fits within the area.
Insert cell
format = d3.format(".1s")
//Allows values to be shown when a mouse is hovered over the map. The .1s will mean values will only be shown up to one decimal point.
Insert cell
radius = d3.scaleThreshold()
.domain(naturalbreaks)
.range(radiusArray)
//Creates the circles seen on the map. It uses the four values calculated below using naturalreaks as the domain, and then it will assign each class value a size based off the values defined in the radiusArray function.
Insert cell
sizeArrayForLegend = Array.from(radiusArray, d=>Math.PI*Math.pow(d, 2))
//Calculates the area of the circles in the legend using the numbers from the radiusArray.
Insert cell
//This changes the radius of the circles on the map.
radiusArray = [6.5, 10, 18, 25]
Insert cell
circleLabels = Array.from(naturalbreaks, d=> format(Math.pow(d, 2)))
Insert cell
colors = d3.scaleThreshold()
.domain(naturalbreaks)
.range(ColorScheme)
Insert cell
//These are the four colors I picked for my map. I went to colorbrewer and selected a single-hue color scheme that was colorblind safe. When "ColorScheme" is put as the range for the colors function above, it will match each of the four classes calculated using natural breaks with one of the colors in the color scheme below in the order that they are in. Here they are organized from lightest to darkest, so the smallest number will get the lightest color and the highest number will be assigned the darkest color.
ColorScheme = ["#eff3ff", "#bdd7e7", "#6baed6", "#2171b5"]
Insert cell
naturalbreaks = simple.ckmeans(attribute, 4).map(v => v.pop())
Insert cell
d3.max(attribute)
Insert cell
attribute = Array.from(points.features, d=>Math.sqrt(d.properties[attributeName]))
Insert cell
//This is the attribute name of the attribute within the point geojson file. By assigning it a shorter name, it will save time and simplify the process since it is quite a long name. If I wanted to change what attribute was displayed, I would just have to change the attribute here and it would update accordingly.
attributeName = "Maryland_Counties_Socioeconomic_Characteristics__2016-2020_from_ACS__20240206(1)@2_Bachelors_degree"
Insert cell
idName = "COUNTY"
Insert cell
//To create this file, I used QGIS to join the geometries of a shapefile of Maryland to the attributes within a csv file. I then used the vector geometry tool to convert each country and the attributes into a centroid. I saved the point data as a new geojson file and uploaded it here.
points = FileAttachment("MarylandCentroids.geojson").json()
Insert cell
basefeatures = topojson.feature(basepolygons, basepolygons.objects.MarylandQGIS)
Insert cell
//import the polygon base map data
basepolygons = FileAttachment("MarylandQGIS(1)(1).json").json()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more