Published
Edited
Nov 23, 2021
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
rawSacData = FileAttachment("sac_aggregate_dataset.csv").csv()
Insert cell
Insert cell
sacData = rawSacData
.map((sac) => {
return {
state: sac.state,
year: sac.year,
cat_take_in:
parseInt(sac.stray_at_large_feline) +
parseInt(sac.relinquished_by_owner_feline) +
parseInt(sac.intake_owner_intended_euthanasia_feline) +
parseInt(sac.transferred_in_from_agency_feline) +
parseInt(sac.other_intakes_feline),
cat_adoption: parseInt(sac.adoption_feline),
cat_died_n_Lost:
parseInt(sac.died_in_care_feline) +
parseInt(sac.lost_in_care_feline) +
parseInt(sac.shelter_euthanasia_feline) +
parseInt(sac.outcome_owner_intended_euthanasia_feline),
dog_take_in:
parseInt(sac.stray_at_large_canine) +
parseInt(sac.relinquished_by_owner_canine) +
parseInt(sac.intake_owner_intended_euthanasia_canine) +
parseInt(sac.transferred_in_from_agency_canine) +
parseInt(sac.other_intakes_canine),
dog_adoption: parseInt(sac.adoption_canine),
dog_died_n_Lost:
parseInt(sac.died_in_care_canine) +
parseInt(sac.lost_in_care_canine) +
parseInt(sac.shelter_euthanasia_canine) +
parseInt(sac.outcome_owner_intended_euthanasia_canine)
};
})
.sort((a, b) => d3.ascending(a.state, b.state))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
sacDataByYearByState = Object.entries(
sacData.reduce((acc, currentValue) => {
let groupKey = currentValue["year"];
if (!acc[groupKey]) {
acc[groupKey] = [];
}
acc[groupKey].push(currentValue);
return acc;
}, {})
).map((d) => ({ year: d[0], states: d[1] }))
Insert cell
Insert cell
stateLabels = sacDataByYearByState[0].states.map((d) => d.state)
Insert cell
petKeys = Object.keys(sacDataByYearByState[0].states[0])
.filter((d) => d != "year")
.filter((d) => d != "state")
Insert cell
Insert cell
years = sacDataByYearByState.map((d) => d.year).concat(["All"])
Insert cell
viewof yearSelection = Inputs.radio(years, { value: "All" })
Insert cell
Insert cell
nodes = [].concat(stateLabels, petKeys).map((d) => ({ name: d }))
Insert cell
Insert cell
data = {
const sankeyData = {
nodes: nodes,
links: links
};

sankeyData.links.map((link) => {
link.source = sankeyData.nodes.findIndex(
(node) => node.name === link.source
);
link.target = sankeyData.nodes.findIndex(
(node) => node.name === link.target
);
});

return sankeyData;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
graph = {
const svg = d3.select(DOM.svg(width, height));

let link = svg
.append("g")
.attr("class", "links")
.attr("fill", "none")
.attr("stroke", "#f05440")
.attr("stroke-opacity", 0.9)
.selectAll("path");

let node = svg
.append("g")
.attr("class", "nodes")
.attr("font-family", "sans-serif")
.attr("font-size", 14)
.selectAll("g");

sankey(data);

link = link
.data(data.links)
.enter()
.append("path")
.attr("d", d3Sankey.sankeyLinkHorizontal())
.attr("opacity", 0.5)
.attr("stroke-width", (d) => Math.max(1, d.width))
.attr("stroke", (d) =>
(d.source.name + d.target.name).includes("dog") ? dogColor : catColor
);

link.append("title").text((d) => `${d.source.name} → ${d.target.name}`);

node = node.data(data.nodes).enter().append("g");

node
.append("rect")
.attr("x", (d) => d.x0)
.attr("y", (d) => d.y0)
.attr("height", (d) => d.y1 - d.y0)
.attr("width", (d) => d.x1 - d.x0)
.attr("fill", "#283250");

node
.append("text")
.attr("x", (d) => d.x0 - 6)
.attr("y", (d) => (d.y1 + d.y0) / 2)
.attr("fill", "#283250")
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text((d) => d.name)
.filter((d) => d.x0 < width / 2)
.attr("x", (d) => d.x1 + 6)
.attr("text-anchor", "start");

node.append("title").text((d) => `${d.name}`);

return svg.node();
}
Insert cell
Insert cell
d3 = require("d3@7")
Insert cell
d3Sankey = require("d3-sankey")
Insert cell
//Read about styling options available at https://github.com/d3/d3-sankey
sankey = d3Sankey
.sankey()
.nodeWidth(30)
.nodePadding(10)
.linkSort(d3.ascending)
.extent([
[horizontalMargin, verticalMargin],
[width - horizontalMargin, height - verticalMargin]
])
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