Published
Edited
Nov 19, 2020
Fork of Maps
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3@6")
Insert cell
data = d3.csvParse(await FileAttachment("nics-firearm-background-checks-1.csv").text(), d3.autoType)
Insert cell
shapefile = d3.json("https://cdn.jsdelivr.net/npm/us-atlas@3/states-albers-10m.json")
Insert cell
Insert cell
// Filter down to most recent, grab columns of interest
most_recent = aq
.from(data)
.select("state", "permit", "permit_recheck")
.objects()
Insert cell
most_recent.filter(d => d.state == "Alabama")
Insert cell
summed = d3.rollup(most_recent, v => d3.sum(v, d => d.permit), d => d.state)
Insert cell
summed_rechecks = d3.rollup(
most_recent,
v => d3.sum(v, d => d.permit_recheck),
d => d.state
)
Insert cell
max_value = d3.max(most_recent, d => (+d["permit"]))
Insert cell
color = d3.scaleSequential([0, max_value], d3.interpolateReds)
Insert cell
color_legend = legend({color:color, title:"Margin of Permits"})
Insert cell
Insert cell
topojson = require("topojson-client@3")
Insert cell
path = d3.geoPath()
Insert cell
// Represent as a Map object to more easily access the values for each state
most_recent_obj = new Map(most_recent.map(d => [d.state, d.permit]))
Insert cell
// Let's make a map!
map = {
// Create the svg
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", 600)
.style("text-anchor", "middle")
.style('font-family', 'sans-serif')
.style("font-size", "12px");

// Add paths for each state
const paths = svg
.selectAll("path")
.data(topojson.feature(shapefile, shapefile.objects.states).features)
.join("path")
.attr("d", path)
.attr("fill", d => {
return color(summed.get(d.properties.name));
});

// Add text for each state
const labels = svg
.selectAll("text")
.data(topojson.feature(shapefile, shapefile.objects.states).features)
.join("text")
.text(d => summed.get(d.properties.name).toFixed(1))
.attr("y", d => path.centroid(d)[1])
.attr("x", d => path.centroid(d)[0]);

// Add a title
const title = svg
.append("text")
.attr('x', width / 2)
.attr("y", 20)
.text("Permits given per state")
.style("font-size", "20px");

// Add a legend
svg
.append("g")
.attr("transform", `translate(${width - 300}, 5)`)
.append(() => color_legend);

// Return svg
return svg.node();
}
Insert cell
md`This is the chloropleth map. One advantage of using the chloropleth map is how popular it is therefore there is a higher chance for the audience to understand my data. Also a chloropleth map does a good job on displaying the numeric change over a surface, which is beneficial for my data since certain states have a drastic difference in comparison to other states in number of permits.
One disadvantage is how the chloropleth maps gives an impression of uniform values within each state. `
Insert cell
data1 = d3.csvParse(await FileAttachment("04-12-2020.csv").text(), d3.autoType)
Insert cell
spike = (length, width = 7) => `M${-width / 2},0L0,${-length}L${width / 2},0`
Insert cell
format = d3.format(",.0f")
Insert cell
length = d3.scaleLinear([0, d3.max(data1, d => d.value)], [0, 200])
Insert cell
spike_chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, 975, 610]);

svg
.append("path")
.datum(topojson.feature(shapefile, shapefile.objects.nation))
.attr("fill", "#e0e0e0")
.attr("d", path);

svg
.append("path")
.datum(
topojson.mesh(shapefile, shapefile.objects.states, (a, b) => a !== b)
)
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("d", path);

const legend = svg
.append("g")
.attr("fill", "#777")
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.selectAll("g")
.data(
length
.ticks(4)
.slice(1)
.reverse()
)
.join("g")
.attr("transform", (d, i) => `translate(${975 - (i + 1) * 18},590)`);

legend
.append("path")
.attr("fill", "red")
.attr("fill-opacity", 0.3)
.attr("stroke", "red")
.attr("d", d => spike(length(d)));

legend
.append("text")
.attr("dy", "1.3em")
.text(length.tickFormat(4, "s"));

svg
.append("g")
.attr("fill", "red")
.attr("fill-opacity", 0.3)
.attr("stroke", "red")
.selectAll("path")
.data(
data1.sort(
(a, b) =>
d3.ascending(a["long_"], b["long_"]) ||
d3.ascending(a["lat"], b["lat"])
)
)
.join("path")
.attr("transform", d => `translate(${d["long_"]})`)
.attr("transform", d => `translate(${d["lat"]})`)
.attr("d", d => spike(length(d.value)))
.append("title")
.text(
d => `${d.title}
${format(d.value)}`
);

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
radius = d3.scaleSqrt(d3.extent(summed, d => d.value), [0, 40])
Insert cell
height = 600
Insert cell
import {chart} with {data as data, my_type as type, my_color as getColor} from "@helloeujin/grid-cartogram"
Insert cell
my_type = "permit"
Insert cell
my_color = (d) => "red"
Insert cell
import { aq, op } from "@uwdata/arquero"
Insert cell
import { legend} from "@d3/color-legend"
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