Published
Edited
Sep 14, 2021
1 fork
Insert cell
Insert cell
d3.extent(all_mask.map(d=>d.cal_unit_price))
Insert cell
viewof max_y = Inputs.range([0, 250], {step: 20, value:250, label: "Max price per mask displayed"})
Insert cell
viewof min_y = Inputs.range([0, max_y], {step: 20, value:0, label: "Min price per mask displayed" })

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")
// // .attr('r', d=>size_scale(d.amount)*1.2)
// })
// .on("mousemove", function(d){
// return tooltip
// .html(`\
// <b>Institution:</b> ${d.Institution_name}<br />\
// <b>Date:</b> ${d3.timeFormat('%Y-%m-%d')(d.Date_order)}<br />\
// <b>Price per Mask:</b> ${d.cal_unit_price}<br />\
// <b>Total Quantity:</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(){
// d3.select(this).transition().attr('stroke-width', "0px")
// // .attr('r', d=>size_scale(d.amount))
// return tooltip.html(``).style("visibility", "hidden");
// })
// }
Insert cell
mask=FileAttachment("mask_scatter@1.csv").csv({typed:true})
Insert cell
data = FileAttachment("penguins.csv").csv({typed: true})
Insert cell
height = 650
Insert cell
x = d3.scaleTime()
.domain([new Date("2020-01-01 00:00:00"), new Date("2021-06-30 00:00:00")])
.range([margin.left, width*0.8 - margin.right])
Insert cell
y = d3.scaleLinear()
.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.amount))])
.range([3, 100]);
Insert cell
color_institution.push("Others")
Insert cell
color_institution
Insert cell
color_scale=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"])
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: 40})
Insert cell
margin2 = ({top: 25, right: 120, bottom: 100, left: 40})
Insert cell
import {
tidy,
startsWith,
groupBy,
summarize,
sum,
mutate,
select,
n,
mean,
everything,
arrange,
desc,
filter,
rate,
TMath,
pivotWider,
pivotLonger,
leftJoin,
count,
map,
complete,
fill
} from '@pbeshai/tidyjs' // observable import
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
style0=html`
<style>
:root {
--text: hsl(153, 73%, 97%);
}

.axis line,
.axis path {
stroke: var(--text);
}

.axis text {
color: var(--text);
transform: rotate(45deg);
}

.circle {
fill: hsla(154, 75%, 86%, 0.8);
stroke: hsla(154, 75%, 86%, 1);
}

.tooltip {
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background: rgba(69,77,93,.9);
border-radius: .1rem;
color: #fff;
display: block;
font-size: 11px;
max-width: 320px;
padding: .2rem .4rem;
position: absolute;
text-overflow: ellipsis;
white-space: pre;
z-index: 300;
visibility: hidden;
}

.tooltip p {
margin: 0;
padding: 0;
}

.label {
font-family: verdana;
fill: hsl(153, 73%, 97%);
}
</style>
`
Insert cell
d3 = require('d3@5')
Insert cell
all_mask=FileAttachment("mask_scatter.csv").csv({typed:true})
Insert cell
mask_arrange=
tidy(
all_mask,
arrange([desc('amount')])
)
Insert cell
mask_arrange2=
tidy(
all_mask,
arrange([desc('order_num')])
)
Insert cell
d3.max(all_mask.map(d=>d.order_num))
Insert cell
x2_amount= d3.scaleLog().base(2)
.domain([min_amount,max_amount]).nice()
.range([margin2.left, width - margin2.right])
Insert cell
xAxis2 = g => g
.attr("transform", `translate(0,${height - margin2.bottom})`)
.call(d3.axisBottom(x2_amount))
Insert cell
yAxis2 = g => g
.attr("transform", `translate(${margin2.left},0)`)
.call(d3.axisLeft(y2))
Insert cell
y2 = d3.scaleLinear()
.domain([min_y,max_y]).nice()
.range([height - margin2.bottom, margin2.top])
Insert cell
d3.extent(all_mask.map(d=>d.amount))
Insert cell
viewof max_amount = Inputs.range([0, 550000000], {step:10000, value:550000000, label:"max quantity of masks in the order displayed"})
Insert cell
viewof min_amount = Inputs.range([1, 500000000], {step:10000, value:1, label:"min quantity of masks in the order displayed" })
Insert cell
d3.max(all_mask.map(d=>d.order_num))
Insert cell
color_legend=swatches({
color: color_scale,
columns: "300px"
})
Insert cell
size_scale2 = d3.scaleSqrt()
.domain([0, d3.max(all_mask.map(d=>d.order_num))])
.range([3, 100]);
Insert cell
legend2={
const values = [5000000, 20000000, 50000000, 100000000]; // hint: add 0 in this array…

return svg`<svg width=${width} height=260px><g transform="translate(200,40)">
${values.map(
v =>
svg`<g><circle cy="${200 - size_scale2(v)}"
r="${size_scale2(v)}" stroke=black fill=none />
<text y="${200 - 2 * size_scale2(v) + 3}"
style="dominant-baseline: hanging; text-anchor: middle;"
>${v}</text>
</g>`
)}</g><g><text x="50" y="15">Size Represent Order Amount in Rand</text></g></svg>`;
}
Insert cell
legend1={
const values = [25000000,100000000, 250000000, 500000000]; // hint: add 0 in this array…

return svg`<svg width=${width} height=260px><g transform="translate(200,40)">

${values.map(
v =>
svg`<g><circle cy="${200 - size_scale(v)}"
r="${size_scale(v)}" stroke=black fill=none />
<text y="${200 - 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
d3.max(all_mask.map(d=>d.amount))
Insert cell
download_svg= DOM.download(() => serialize(chart), undefined, "Save as SVG")
Insert cell
download_svg2= DOM.download(() => serialize(chart2), undefined, "Save as SVG")
Insert cell
chart = {
const svg = d3.select(DOM.svg(width,height))
.attr('id', 'grap')

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

svg.append("g")
.call(yAxis);
svg.append("g").append("text").attr("x",width-margin.right-100).attr("y",height-margin.top+20).text("Date of Order")
svg.append("g").append("text").attr("x",margin.left).attr("y",margin.top-10).text("Price per mask(R)")

return svg.node();
}
Insert cell
import {rasterize, serialize} from "@mbostock/saving-svg"
Insert cell
chart2 = {
const svg = d3.select(DOM.svg(width,height))
.attr('id', 'grap2')
svg.append("g")
.selectAll("circle")
.data(mask_arrange2)
.join("circle")
.filter(d => (d.cal_unit_price>min_y)&(d.cal_unit_price<max_y))
.attr("fill",d=>color_institution.includes(d.Institution_name)?color_scale(d.Institution_name):"#ccc")
.attr("cx", d => x2_amount(d.amount))
.attr("cy", d => y2(d.cal_unit_price))
.attr("r", d=>size_scale2(d.order_num));
svg.append("g")
.call(xAxis2);

svg.append("g")
.call(yAxis2);
svg.append("g").append("text").attr("x",width-margin2.right*2.5).attr("y",height-margin2.top-margin2.bottom/5).text("Total quantity of masks in the order")
svg.append("g").append("text").attr("x",margin2.left).attr("y",margin2.top-10).text("Price per mask(R)")
return svg.node();
}
Insert cell
tooltip2 = {
chart2
const tooltip2 =
d3.select('body').append('div')
.attr('class', 'tooltip')
.style('position', 'absolute')
.style('visibility', 'hidden').text('ege')

d3.selectAll("circle")
.on("mouseover", function(d){
d3.select(this).transition().attr('stroke-width', "3px").attr("stroke","red")
})
.on("mousemove", function(d){
return tooltip2
.html(`\
<b>Institution:</b> ${d.Institution_name}<br />\
<b>Date:</b> ${d3.timeFormat('%Y-%m-%d')(d.Date_order)}<br />\
<b>Price per Mask:</b> ${d.cal_unit_price}<br />\
<b>Total Quantity:</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(){
d3.select(this).transition().attr('stroke-width',"0px")
return tooltip2.html(``).style("visibility", "hidden");
})
}
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