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

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