Published
Edited
Dec 12, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
reviewMonthlyCounts = cleanedData
.map((d) => ({
...d,
counts: d.reviews.reduce((acc, val) => {
const key = val.date.getUTCFullYear() + "-"+ val.date.getUTCMonth()
if (!acc[key]) {
acc[key] = [];
}
// Add object to list for given key's value
acc[key].push(val);
return acc;
}, {})
}))
.map((d) => ({
...d,
counter: Object.entries(d.counts).reduce(
(acc, val) => ({ ...acc, [val[0]]: val[1].length }),
{}
)
}))
Insert cell
monthCounts = reviewMonthlyCounts.map(d=>Object.entries(d.counter).map(e=>({date: new Date(e[0].split('-')[0],e[0].split('-')[1]), count:(e[1]), product:d.name}))).flat().sort((a,b)=>d3.ascending(a.date,b.date))
Insert cell
import {Streamgraph} from "@d3/streamgraph"
Insert cell
chart = Streamgraph(monthCounts, {
x: d => d.date,
y: d => d.count,
z: d => d.product,
yLabel: "↑ Unemployed persons",
width,
height: 600
})
Insert cell
Insert cell
boundaryDates = d3.extent(
cleanedData.map((d) => d.reviews).flat(),
(d) => d.date
)
Insert cell
timeScale = d3
.scaleTime()
.domain(boundaryDates)
.range([margin, width - margin])
Insert cell
productScale = d3
.scalePoint()
.domain(cleanedData.map((d) => d.name))
.range([margin, height - margin])
Insert cell
Insert cell
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("width", width).attr("height", height);
const bg = svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "#445");

svg
.selectAll(".timelines")
.data(cleanedData)
.enter()
.append("line")
.attr("stroke", "#D3D3D3")
.attr("x1", margin)
.attr("x2", width - margin)
.attr("y1", (d) => productScale(d.name))
.attr("y2", (d) => productScale(d.name));

for (let product of cleanedData) {
svg
.selectAll(".reviewDots")
.data(product.reviews)
.enter()
.append("circle")
.attr("fill", (d) => d3.interpolateMagma(d.stars / 5))
.attr("cx", (d) => timeScale(d.date))
.attr("cy", (d) => productScale(product.name))
.attr("r", 3)
.attr("opacity", 0.5);
}

svg
.selectAll(".labels")
.data(boundaryDates)
.enter()
.append("text")
.attr("x", (d) => timeScale(d))
.attr("y", margin / 2)
.attr("fill", "white")
.attr("text-anchor", "middle")
.text((d) => d.toLocaleString().split(",")[0]);

return svg.node();
}
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