Published
Edited
Sep 14, 2021
Insert cell
Insert cell
viewof max_y = Inputs.range([0, 550000000], {step: 20, value:550000000, label: "Max number of masks displayed"})
Insert cell
viewof min_y = Inputs.range([1, max_y], {step: 20, value:100, label: "Min number of masks displayed" })

Insert cell
height = 750
Insert cell
x = d3.scaleTime()
.domain([new Date("2020-01-01 00:00:00"), new Date("2021-12-31 00:00:00")])
.range([margin.left, width*0.9 - margin.right])
Insert cell
y = d3.scaleLog().base(2).domain([min_y,max_y]).nice()
.range([height - margin.bottom, margin.top])
Insert cell
size_scale = d3.scaleSqrt()
.domain([0, d3.max(all_mask.map(d=>d.cal_unit_price))])
.range([1, 50]);
Insert cell
color_institution.push("Others")
Insert cell
color_institution
Insert cell
color_scale=d3.scaleOrdinal()
.domain(color_institution_use)
.range(["#025DF4","#DB6BCF","#2498D1","#BBBDE6","#4045B2","#21A97A","#FF745A","#007E99","#FFA8A8","#2391FF","#FFC328","#A0DC2C","#946DFF","#626681","#EB4185","#CD8150","#36BCCB","#327039","#803488","#83BC99","#ccc"])
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x))
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y))
Insert cell
margin = ({top: 25, right: 20, bottom: 100, left: 80})
Insert cell
Insert cell
institution_data=tidy(
all_mask,
groupBy('Institution_name', [
summarize({ total: n('value') })
]),
arrange([desc('total')])

)
Insert cell
color_institution=institution_data.map(d=>d.Institution_name).slice(0,20)
Insert cell
color_institution_use=color_institution.map(d=>d.replaceAll(/\W/g,"").toLowerCase())
Insert cell
Insert cell
d3 = require('d3@5')
Insert cell
all_mask=FileAttachment("mask_scatter@3.csv").csv({typed:true})
Insert cell
mask_arrange=
tidy(
all_mask,
arrange([desc('cal_unit_price')])
)
Insert cell
color_legend=swatches({
color: d3.scaleOrdinal()
.domain(color_institution)
.range(["#025DF4","#DB6BCF","#2498D1","#BBBDE6","#4045B2","#21A97A","#FF745A","#007E99","#FFA8A8","#2391FF","#FFC328","#A0DC2C","#946DFF","#626681","#EB4185","#CD8150","#36BCCB","#327039","#803488","#83BC99","#ccc"]),
columns: "300px"
})
Insert cell
legend1={
const values = [10,50, 125, 250]; // hint: add 0 in this array…

return svg`<svg width=${width*0.9} height=150px><g transform="translate(200,0)">

${values.map(
v =>
svg`<g><circle cy="${135 - size_scale(v)}"
r="${size_scale(v)}" stroke=black fill=none />
<text y="${135 - 2 * size_scale(v) + 3}"
style="dominant-baseline: hanging; text-anchor: middle;"
>${v}</text>
</g>`
)}</g><g><text x="50" y="15">Size Represents Number of Masks in the Order</text></g></svg>`;
}
Insert cell
download_svg= DOM.download(() => serialize(chart), undefined, "Save as SVG")
Insert cell
chart = {
const svg = d3.select(DOM.svg(width*0.9,height))
.attr('id', 'grap')

svg.append("g")
.selectAll("circle")
.data(mask_arrange)
.join("circle")
.filter(d => (d.amount>min_y)&(d.amount<max_y))
.attr("fill",d=>color_institution_use.includes(d.Institution_name.replaceAll(/\W/g,"").toLowerCase())?color_scale(d.Institution_name.replaceAll(/\W/g,"").toLowerCase()):"#ccc")
.attr("cx", d => x(d.Date_order))
.attr("cy", d => y(d.amount))
.attr("r", d=>size_scale(d.cal_unit_price))
.attr("class",d=>d.Institution_name.replaceAll(/\W/g,"").toLowerCase())
svg.append("g")
.call(xAxis);

svg.append("g")
.call(yAxis);
svg.append("g").append("text").attr("x",width*0.9-margin.right-100).attr("y",height-margin.top-40).text("Date of Order")
svg.append("g").append("text").attr("x",margin.left).attr("y",margin.top-10).text("Number of masks purchased in the order")

return svg.node();
}
Insert cell
tooltip = {
chart
const tooltip =
d3.select('body').append('div')
.attr('class', 'tooltip')
.style('position', 'absolute')
.style('visibility', 'hidden').text('ege')

d3.select("#grap").selectAll("circle")
.on("mouseover", function(d){
d3.select(this).transition().attr('stroke-width', "3px").attr("stroke","red")
const class_name="."+d.Institution_name.replaceAll(/\W/g,"").toLowerCase()
d3.selectAll(class_name).transition().attr('stroke-width', "3px").attr("stroke","red")
})
.on("mousemove", function(d){
return tooltip
.html(`\
<b>Institution:</b> ${d.Institution_name}<br />\
<b> Order Date:</b> ${d3.timeFormat('%Y-%m-%d')(d.Date_order)}<br />\
<b>Price per Mask:</b> ${d.cal_unit_price}<br />\
<b>Total Number of masks:</b> ${d.amount}<br />\
<b>Order Amount in Rand:</b> ${d.order_num}<br />\
`)
.style("top", (d3.event.pageY-10)+"px")
.style("left",(d3.event.pageX+20)+"px")
.style("visibility", "visible");
})
.on("mouseout", function(d){
d3.select(this).transition().attr('stroke-width', "0px")
const class_name="."+d.Institution_name.replaceAll(/\W/g,"").toLowerCase()
d3.selectAll(class_name).transition().attr('stroke-width', "0px")
return tooltip.html(``).style("visibility", "hidden");
})
}
Insert cell
import {rasterize, serialize} from "@mbostock/saving-svg"
Insert cell
import {swatches} from "@d3/color-legend"
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