Published
Edited
Apr 24, 2020
Insert cell
Insert cell
Insert cell
render_data_table(all_data.slice(0, 10))
Insert cell
_.uniqBy(all_data, d => d.artist)
Insert cell
Insert cell
Insert cell
line_data = d3
.nest()
.key(d => d.group)
.rollup(v => v.sort((a, b) => a.x - b.x))
.entries(chart_data)
.filter(d => d.value.length > 0)
Insert cell
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

svg.append("g").call(xAxis);

svg.append("g").call(yAxis);

// Add an x axis label
svg.append('text').call(xLabel);

// Add an x axis label
svg.append('text').call(yLabel);

// Add some points
svg
.selectAll("circle")
.data(chart_data, d => d.id)
.join("circle")
.attr("r", d => {
return d.group === search_value ? 15 : 3; // Change point size based on search value
})
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y))
.style("fill", d => {
return d.group === search_value ? "red" : "blue"; // Change point color based on search value
});

// Add lines
svg
.selectAll("path")
.data(line_data)
.join("path")
.attr('id', (d, i) => 'line-' + i) // assign an id
.attr("d", d => lineGenerator(d.value)) // draw the path
// Set the dasharray for animating the line drawing
.attr("stroke-dasharray", (d, i) => {
// Get the path length (if the node exists.... not sure why it wouldn't....)
if (d3.select('#line-' + i).node() !== null) {
const length = d3
.select('#line-' + i)
.node()
.getTotalLength();
return length + " " + length;
}
})
// Set the "dash offset" to the length of the line
.attr("stroke-dashoffset", (d, i) => {
if (d3.select('#line-' + i).node() !== null) {
const length = d3
.select('#line-' + i)
.node()
.getTotalLength();
return length;
}

return 1;
})
.style("fill", "none")
.attr("stroke-width", "1px")
.attr("stroke", "black")
// Animate the stroke dash offset, one at a time, depending on their index
.transition()
.delay((d, i) => i * 50) // delay each one
.duration(3000)
.attr("stroke-dashoffset", 0);
return svg.node();
}
Insert cell
Insert cell
lineGenerator = d3
.line()
.curve(d3.curveCardinal)
.x(d => x(d.x)) // .x -> x values to use for line
.y(d => y(d.y)) // .y -> y values to use for line
Insert cell
x_domain = d3.extent(chart_data, d => d.x)
Insert cell
x = d3
.scaleLinear()
.domain(x_domain)
.range([margin.left, width - margin.right])
Insert cell
y = d3
.scaleLog()
.domain(d3.extent(chart_data, d => d.y))
.range([height - margin.bottom, margin.top])
Insert cell
Insert cell
xLabel = ele =>
ele
.text("Year")
.attr("x", width / 2)
.attr("y", height - margin.bottom + 30)
.style('font-family', "sans-serif")
Insert cell
yLabel = ele =>
ele
.text("Total Points Awarded")
.attr(
"transform",
`translate(${margin.left - 40}, ${height / 2})rotate(-90)`
)
.style("text-anchor", "middle")
.style('font-family', "sans-serif")
Insert cell
xAxis = g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickFormat(d => d))
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y))
Insert cell
Insert cell
import { autoSelect } from "@jashkenas/inputs"
Insert cell
all_data = d3.csv(
"https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-04-14/rankings.csv"
)
Insert cell
d3 = require("d3@5")
Insert cell
margin = ({ top: 20, right: 30, bottom: 30, left: 70 })
Insert cell
height = 500
Insert cell
import { render_data_table, table_styles } from "@info474/utilities"
Insert cell
_ = require("lodash")
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