Public
Edited
May 9, 2023
Insert cell
Insert cell
Insert cell
//Analyzing the map: from looking at the map we can see there are much fewer traffic deaths in the upper midwest/ northwest. Primarily this could be due to the overall size of the population of that state as we can see larger states such as California, Florida and Texas all have a high number of deaths. It is interesting how many of the states east of the Mississippi River have a similar range of traffic deaths. The symbols to lead to easy visualization of outliers such as West Virgin being so much smaller than all of the surrounding states. I also found it interesting how in some areas that have higher amounts of snow there is much less deaths than areas that don’t get snow

graduatedSymbols = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
//This is where we create the basemap from polygon topojson
svg.append("path") //basemap
.datum(topojson.feature(basepolygons, basepolygons.objects.states_simple)) //defines datum
.attr("fill", "#ccc") //this sets its symbology (basemap) #ccc is what is being used but you could also use words like 'blue' without a #
.attr("d", path_basemap);
svg.append("path")// this addes the border lines between states
.datum(topojson.mesh(basepolygons, basepolygons.objects.states_simple, (a, b) => a !== b))
.attr("fill", "none")
.attr("stroke", "black")
//here you can alter the color of lines between the states
.attr("stroke-linejoin", "round")
.attr("d", path_basemap);
svg.append("g")//adding the circles onto the map
.selectAll("circle") //this is where we determine the type of point symbol, the code below defines the radius because we are using a circle
.data(points.features
.map(d => (d.value = Math.sqrt(d.properties[attributeName]), d))
//svg.append("g")
//.selectAll("circle")
//.data(points.features
//.map(d => (d.value = Math.sqrt(d.properties[attributeName]), d))
//these lines of code link the values of an attribute
.sort((a, b) => b.value - a.value))
.join("circle")
.attr("transform", d => `translate(${path_points.centroid(d)})`)
.attr("r", d => radius(d.value)) //here we create the scale for mapping the values of the attributes to the radius
//pass the attribute value into the radius to return the size of our circle
.attr("fill", d => colors(d.value))
//above this is how we map the maps to fill the colors
// here 'colors' pulls the colorbrewer scheme I made below and uses it here
.attr("fill-opacity", 0.85)
//this is how we can change the opacity
.attr("stroke", "black")
//this is where you can change the outline color of the points, currently I have it set to 'black'
.attr("stroke-width", .5)
//this is where you can change the thickness or (width) of the outline around the point, here it is set to .5
.append("title")
.text(d => `${d.properties[idName]} : ${format(d.properties[attributeName])}`);
//this is what is used to display the values when you hover over each point
return svg.node();
}
Insert cell
//more legend information
symbolLegendDef = {
return {
type: "symbol",
title: attributeName,
fill: "symbolColor",
size: "symbolSize",
direction: 'Horizontal',
columns: undefined,
rowPadding: 5,
columnPadding: 5,
clipHeight: undefined,
titleOrient: 'Top',
symbolStrokeColor: '#000',
symbolStrokeWidth: .5
};
}
Insert cell
height = 610
Insert cell
width = 975
Insert cell
path_points = d3.geoPath().projection(projection)
Insert cell
path_basemap = d3.geoPath().projection(projection)
Insert cell
projection = d3.geoAlbers()
Insert cell
format = d3.format(".2s")
Insert cell
//proportional symbols
//radius = d3.scaleSqrt([0, d3.max(attribute)], [0, 30])
Insert cell
radius = d3.scaleThreshold()
.domain(naturalbreaks)
.range(radiusArray)
Insert cell
sizeArrayForLegend = Array.from(radiusArray, d=>Math.PI*Math.pow(d, 2))
Insert cell
radiusArray = [3, 9, 18, 27]
Insert cell
circleLabels = Array.from(naturalbreaks, d=> format(Math.pow(d, 2)))
//this is used to label the circles in the legend
Insert cell
colors = d3.scaleThreshold()
.domain(naturalbreaks)
.range(YlOrRd)
Insert cell
YlOrRd = ["#feebe2", "#fbb4b9", "#f768a1", "#ae017e",]
//this is where we create the colors by using hex codes, these used are from colorbrewer to insure that they are colorblind safe
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
attributeName = "crashdeaths_CRASH"
//variable you want to visualize, here is my new attribute, Traffic Fatalities by State
Insert cell
idName = "STATE_NAME"
Insert cell
//import the point data (geojson)
points = FileAttachment("states48_points_CrashDeaths.geojson").json()
//joined the Traffic Fatalities by State csv to the geojson file in QGIS by using STATE as a common attribute, this allowed me to match up each state with the corresponding about of traffic deaths
// you can also join them inside observable by first reading the csv using CSV_data = d3.csvParse(awate FileAttachment("your csv file").text)then join them using data = object.assign(map(CSV_data))
Insert cell
//import the polygon base map data
basepolygons = FileAttachment("states_simple.json").json()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more