Published
Edited
Sep 1, 2022
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, noSplitHeight + margin.top + margin.bottom]);

const wrapper = svg
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);

// Add x-Axis
wrapper.append("g").call(xAxis);

// add yAxis
const yAxisContainer = wrapper
.append("g")
.attr("transform", `translate(-10,0)`);

const circles = wrapper
.append("g")
.attr("className", "circles")
.selectAll("circle")
.data(games)
.join("circle")
.attr("r", (d) => r(d.runs))
.attr("fill", (d) => color(d.win_loss))
.attr("x", (d) => x(d.runs))
.attr("y", (d) => y(d.year) + y.bandwidth() / 2);

force.on("tick", () => {
circles
.transition()
.ease(d3.easeLinear)
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
});

invalidation.then(() => force.stop());

return Object.assign(svg.node(), {
update(split) {
let height = split ? splitHeight : noSplitHeight;
let years = [...yearGroups.keys()].sort();

// Update height of svg object
const t = d3.transition().duration(750);
svg.transition(t).attr("viewBox", [0, 0, width, height]);

// Update domain of y-Axis
y.domain(split ? years : ["All"]);
y.range(
split
? [splitHeight - margin.top - margin.bottom, 0]
: [noSplitHeight - margin.top - margin.bottom, 0]
);
yAxisContainer
.call(yAxis, y, split ? years : ["All"])
.call((g) => g.select(".domain").remove())
.call((g) => g.selectAll(".tick line").remove());

// Update simulation
force.force(
"y",
split
? d3.forceY((d) => y(d.year) + y.bandwidth() / 2) // If split by year align by year
: d3.forceY((noSplitHeight - margin.top - margin.bottom) / 2)
); // If not split align to middle
//force.nodes(running);
force.alpha(1).restart();

// Update median line
// medianLine
// .transition(t)
// .attr("y2", split ? splitHeight - 20 : noSplitHeight);
}
});
}
Insert cell
median = d3.median(games, (d) => d.runs)
Insert cell
medianHits = d3.median(games, (d) => d.hits)
Insert cell
medianRuns = d3.median(games, (d) => d.runs)
Insert cell
medianHomeRuns = d3.median(games, (d) => d.home_runs)
Insert cell
Insert cell
splitHeight = 900
Insert cell
Insert cell
noSplitHeight = 500
Insert cell
Insert cell
chart.update(split);
Insert cell
force = d3
.forceSimulation(games)
.force("charge", d3.forceManyBody().strength(0))
.force(
"x",
d3.forceX().x((d) => x(d.runs))
)
.force(
"y",
d3.forceY((d) => y(d.year))
)
.force(
"collision",
d3.forceCollide().radius((d) => r(d.hits))
)
Insert cell
Insert cell
groups = d3.group(games, (d) => d.year)
Insert cell
x = d3.scaleLinear()
.domain(d3.extent(games, d => d.hits))
.range([0, innerWidth])
Insert cell
y = d3.scaleBand()
.domain(['All'])
.range([noSplitHeight, 0])
Insert cell
r = d3.scaleSqrt()
.domain(d3.extent(games, d => d.runs))
.range([1, 10])
Insert cell
xAxis = (g) =>
g
.call(d3.axisTop(x).tickFormat((d) => `${d} runs`))
.call((g) => g.select(".domain").remove())
.call((g) =>
g
.append("text")
.attr("x", innerWidth)
.attr("y", 20)
.attr("font-weight", "bold")
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text("How many runs they scored →")
)
Insert cell
yAxis = g => g
.call(d3.axisLeft(y).ticks(8))
.call(g => g.select('.domain').remove())
.call(g => g.selectAll('.tick line').remove())
Insert cell
color = d3.scaleOrdinal(
d3.extent(games, (d) => d.win_loss),
d3.schemeTableau10
)
Insert cell
innerWidth = width - margin.left - margin.right
Insert cell
margin = ({top: 30, right: 30, left: 120, bottom: 30})
Insert cell
Insert cell
yearGroups = d3.group(games, (d) => d.year)
Insert cell
gameYears = d3.group(games, (d) => d.year)
Insert cell
Insert cell
games = d3.csvParse(
await FileAttachment("dodgers_games_2012-2021.csv").text(),
(d) => {
return {
year: +d.year,
runs: +d.runs_scored,
home_runs: +d["hr"],
hits: +d["h"],
win_loss: d["win_loss"]
};
}
)
Insert cell
d3 = require('d3@5', 'd3-array@^2.2')
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