Published
Edited
Nov 2, 2021
Insert cell
Insert cell
viewof hideCheckbox = Inputs.checkbox(["Yes, show them."], {label: "Show 0 death petals?"})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fixedWeekNo = 96 // 96 = start date at 94 = data cut off date oct 9
Insert cell
// startDateOfMostRecentSelectedWeek = yearWeekLookUp(desiredData.map(d=>d[regions.indexOf(xxx)]).slice(0,z+1)[fixedWeekNo-1]['yearWeek'])
Insert cell
// viewof z = Scrubber(Array.from({length: desiredData.length}, (_, z) => z), {delay: 200}, {autoplay: false})
viewof z = Scrubber(Array.from({length: fixedWeekNo}, (_, z) => z), {delay: 200}, {autoplay: false})
Insert cell
desiredData.map(d=>d[regions.indexOf(xxx)]).slice(0,z+1)
Insert cell
{
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height]); // min-x, min-y, width , height

const axis = svg.selectAll(".axis")
.data([1,0])
.enter()
.append("g")
.attr("class", "axis");

axis.append("line")
.attr("x1", -width/2)
.attr("y1", 0)
.attr("x2", width/2)
.attr("y2", 0)
.attr("class", "line")

axis.append("line")
.attr("x1", 0)
.attr("y1", -height/2)
.attr("x2", 0)
.attr("y2", height/2)
.attr("class", "line")


var slicedData = desiredData.map(d=>d[regions.indexOf(xxx)]).slice(0,z+1)
svg
.append('g')
.selectAll("ellipse")
.data(slicedData)
.join("ellipse")
.attr("visibility", function (d){
return (hideCheckbox.length ===0 & d.deaths ==0)? "hidden": "visible"
})
.attr("cy", d => rScale(maxDeaths) - rScale(d.deaths))
.attr("ry", d => rScale(d.deaths))
// .attr("rx", d => rScale(d.deaths)/3)
// SPECIAL SCALE TO RESIZE SINGPAORE'S LARGER PETALS
.attr("rx", d => (d.region === "Singapore" & d.deaths > 30)? rScale(d.deaths)/5 : rScale(d.deaths)/3)
// .attr("fill", d => colorByContinent(d.region, 1))
.attr("fill", function (d, i){
return (i < indexOf2021)? colorByContinent(d.region, 1, colors_):colorByContinent(d.region, 1)
})
.attr("stroke", "white")
// .attr("stroke-width", strokeWidth)
.attr("stroke-width", function (d,i) {
// mark for max deaths in 2020 & 2021
return( d.yearWeek === maxYearWeek2021 || d.yearWeek === maxYearWeek2020? 1.5: strokeWidth)
})
.attr('transform', function(d, i) {
var rx = Math.cos(xcos(i)) * outerRadius;
var ry = Math.sin(ysin(i)) * outerRadius;
return `translate(${rx},${ry})
rotate(${xcos(i) * 180 / Math.PI + 90})
scale(${0.8})`;
})

// to add 1st year's ellipse on top of 2nd year's
if(z > indexOf2021){
svg
.append('g')
.selectAll("ellipse")
.data(slicedData.splice(0,indexOf2021))
.join("ellipse")
.attr("visibility", function (d){
return (hideCheckbox.length ===0 & d.deaths ==0)? "hidden": "visible"
})
.attr("cy", d => rScale(maxDeaths) - rScale(d.deaths))
.attr("ry", d => rScale(d.deaths))
.attr("rx", d => rScale(d.deaths) / 3)
.attr("fill", function (d, i){
return (i < indexOf2021)? colorByContinent(d.region, 1, colors_):colorByContinent(d.region, 1)
})
.attr("stroke", "white")
.attr("stroke-width", function (d,i) {
return( d.yearWeek === maxYearWeek2021 || d.yearWeek === maxYearWeek2020? 1.5: strokeWidth)
})
.attr('transform', function(d, i) {
var rx = Math.cos(xcos(i)) * outerRadius;
var ry = Math.sin(ysin(i)) * outerRadius;
return `translate(${rx},${ry})
rotate(${xcos(i) * 180 / Math.PI + 90})
scale(${0.8})`;
})
}

// color the last ellipse
// svg.selectAll(".ellipse:nth-last-child(1)")
// .attr("fill", d => colorByContinent3(d.region, 1))
// .attr("stroke", "white")
// .attr("stroke-width", 1.5)

let displayedYearWeek = desiredData.map(d=>d[regions.indexOf(xxx)])[z]["yearWeek"];
svg.append("text")
.attr("class", "label")
.attr("x", 0)
.attr("y", -15)
.text(formatter(yearWeekLookUp(displayedYearWeek)))
.attr("transform", "rotate(90)");

svg.append("text")
.attr("class", "label")
.attr("x", 0)
.attr("y", 0)
.text(desiredData.map(d=>d[regions.indexOf(xxx)])[0].region)
.attr("transform", "rotate(90)");

svg.append("text")
.attr("class", "label")
.attr("x", 0)
.attr("y", 15)
.text(desiredData.map(d=>d[regions.indexOf(xxx)])[z]["cumuDeaths"])
.attr("transform", "rotate(90)");
svg.append("text")
.attr("class", "label")
.attr("x", 0)
.attr("y", 30)
.text(`+${desiredData.map(d=>d[regions.indexOf(xxx)])[z]["deaths"]}`)
.attr("transform", "rotate(90)");


svg.attr("transform", "rotate(270)");
return svg.node()
}
Insert cell
formatter = d3.timeFormat("%d %b, %Y")
Insert cell
formatter(yearWeekLookUp('2020-3'))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// sin cos 1.95
// magicNumber = 3 / 8
//magicNumber = 3 / 12 // ~50 weeks = one round; 1/4 circle = one season
magicNumber = 2.3 / 12 // ~50 weeks = one round; 1/4 circle = one season
Insert cell
xcos = d3.scaleLinear()
.domain([0, desiredData[0].length])
.range([Math.PI * 0, Math.PI * magicNumber]);
Insert cell
ysin = d3.scaleLinear()
.domain([0, desiredData[0].length])
.range([Math.PI * 0, Math.PI * magicNumber]);
Insert cell
Insert cell
// maxDeaths = d3.max(desiredData.map(d => d3.max(d)).map(d => d.deaths))
Insert cell
minDeaths = 0
Insert cell
outerRadius = 190
// outerRadius = 120
Insert cell
Insert cell
regions = desiredData[0].map(d=>d.region)
Insert cell
rScaleNum = 3.6
// rScaleNum = 9
Insert cell
rScale = d3.scaleLinear()
.domain([minDeaths, maxDeaths])
.range([10, height / rScaleNum])
Insert cell
Insert cell
{
return html`<p style="font-family:sans-serif;font-size:small;color:grey;line-height:1.8em;">
${regions
.map(
c => `<span style="background:${opacityLegend(colorByContinent(c))}; padding:7px; color:white;"> ${c} </span>`
)
.join("")}`;
}
Insert cell
//colors = ["#FFD400","#E08523","#C7246B","#24A299","#67A6DA","#9BBCCE"]
//colors_ = ["#F9E280","#D8A373","#C16893","#6DBCB5","#9BBCCE","#7C7099"]
Insert cell
// default // first year
colors = Array(5).fill("#E08523")
Insert cell
colors_ = Array(5).fill("#D8A373")
Insert cell
function colorByContinent(expr, op, palette = colors){
var c = palette.map(d => opacityTweak(d,op))
// var c = d3.schemePastel1.map(d => opacityTweak(d,op))
switch (expr) {
case regions[0]:
return c[0]
break;
case regions[1]:
return c[1]
break;
case regions[2]:
return c[2]
break;
case regions[3]:
return c[3]
break;
case regions[4]:
return c[4]
break;
case regions[5]:
return c[5]
break;
return c[6]
}}
Insert cell
function opacityTweak(color, number) {
const {l, c, h, opacity} = d3.lch(color);
return d3.lch(l, c, h,opacity* number);
}
Insert cell
Insert cell
Insert cell
height = 700
Insert cell
// width = height
Insert cell
margin = 50
Insert cell
// desiredData = desiredData1
Insert cell
Insert cell
import {lastDate} from "@spepechen/dataprep-v2-2"
Insert cell
Insert cell
import {yearWeekLookUp} from "@spepechen/dataprep-v2-2" // countries data
Insert cell
yearWeekLookUp("2020-8")
Insert cell
desiredData = desiredDataRaw
// desiredData = sg
Insert cell
Insert cell
maxDeaths = d3.max(desiredDataRaw.map(d => d[regions.indexOf(xxx)]).map(d => d.deaths))
Insert cell
Insert cell
Insert cell
Insert cell
maxYearWeek2021 = arr2021.filter(d => d.deaths == maxDeaths2021)[0].yearWeek
Insert cell
maxYearWeek2020 = arr2020.filter(d => d.deaths == maxDeaths2020)[0].yearWeek
Insert cell
maxDeaths2021Date = formatter(yearWeekLookUp(arr2021.filter(d => d.deaths == maxDeaths2021)[0].yearWeek))
Insert cell
maxDeaths2020Date = formatter(yearWeekLookUp(arr2020.filter(d => d.deaths == maxDeaths2020)[0].yearWeek))
Insert cell
Insert cell
arr2021 = desiredDataRaw.map(d => d[regions.indexOf(xxx)]).filter(d => d.yearWeek.split("-")[0] == "2021")
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