Public
Edited
Feb 14, 2024
Insert cell
Insert cell
Insert cell
Insert cell
dataFile = await FileAttachment("fake_app_download_rating.csv").text()
Insert cell
dataset = d3.csvParse(dataFile, (row) => ({
app_name: row.app_name,
downloads: parseInt(row.downloads),
average_rating: parseFloat(row.average_rating),
thirty_day_keep: parseFloat(row.thirty_day_keep)
}))
Insert cell
w = 600
Insert cell
h = dataset.length * 24
Insert cell
// our range is limited from 0 to width - 100,
// which is for the 80 pixels on left for axis and
// 20 pixels on right for padding
xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d.downloads)])
.rangeRound([0, w - 80 - 20]);
Insert cell
datasetAppNames = dataset.map((d) => d.app_name)
Insert cell
// using scale band to work with nominal values
// the Array.map() call allows us to get a new array
// by calling a function on each item of the source array
// here it pulls out the app_name
yScale = d3.scaleBand()
.domain(datasetAppNames)
.rangeRound([20, h - 20]);
Insert cell
// d3 allows scaling between colors
colorScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d.downloads)])
.range(['#ccf', '#88d']);
Insert cell
makeChart1(dataset)
Insert cell
makeChart1 = (dataset) => {
//Sort the data by downloads
//Uses built-in Array.sort() with comparator function
dataset.sort((a, b) => b.downloads - a.downloads);

const chart = d3.create("svg").attr("width", w).attr("height", h);

const bars = chart
.selectAll("rect")
.data(dataset)
.join("rect")
.attr("x", 80)
.attr("y", (d) => yScale(d.app_name))
.attr("width", 0)
.attr("height", 20)
.style("fill", "#88d");

// AXES
chart
.append("g")
.classed("axis", true)
.attr("transform", `translate(80, ${h - 20})`)
.call(d3.axisBottom(xScale));

chart
.append("g")
.classed("axis", true)
.attr("transform", `translate(80,0)`)
.call(d3.axisLeft(yScale));

//First Transition
bars.transition()
.duration(500)
.delay((d, i) => i * 35)
.attr("width", d => xScale(d.downloads))
.style("fill", d => colorScale(d.downloads))
//Second Transition
.transition()
.duration(200)
.delay((d, i) => (i + 1) * 35)
.style("fill", "#88d")
//Third transition
.transition()
.duration(200)
.delay((d, i) => (i + 2) * 35)
.style("fill", d => colorScale(d.downloads));

return chart.node();
}
Insert cell
Insert cell
d3 = require("d3@7")
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