Public
Edited
Aug 17, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
margin = ({top: 10, bottom: 45, left: 75, right: 10})
Insert cell
visWidth = width - margin.left - margin.right
Insert cell
visHeight = 400 - margin.top - margin.bottom
Insert cell
Insert cell
maxPopulation = d3.max(data, d => d.population)
Insert cell
meanPopulation = d3.mean(data, d => d.population)
Insert cell
populationScale = d3.scaleLinear()
.domain([0, maxPopulation])
.range([visHeight, 0])
Insert cell
countries = data.map(d => d.country)
Insert cell
countryScale = d3.scaleBand()
.domain(countries)
.range([0, visWidth])
.padding(0.2)
Insert cell
countryScale.bandwidth()
Insert cell
Insert cell
viewof barplot = Inputs.radio(['visible','hidden'],{label:"barPlot"})
Insert cell
viewof lolliplot = Inputs.radio(['visible','hidden'],{label:"LolliPlot"})
Insert cell
xAxis = d3.axisBottom(countryScale)
Insert cell
{
// create and select an svg element that is the size of the bars plus margins
const svg = d3.create('svg')
.attr('width', visWidth + margin.left + margin.right)
.attr('height', visHeight + margin.top + margin.bottom);
// append a group element and move it left and down to create space
// for the left and top margins
const g = svg.append("g")
.attr('transform', `translate(${margin.left}, ${margin.top})`);
// bind our data to rectangles
g.selectAll('rect')
.data(data)
.join('rect')
// set attributes for each bar
.attr('x', d => countryScale(d.country))
.attr('y', d => populationScale(d.population))
.attr('height',d => visHeight - populationScale(d.population))
.attr('width', countryScale.bandwidth())
.attr('fill', 'steelblue')
.attr('id','bar')
.attr('visibility',barplot)
const line = svg.append('line')
.attr('x1',margin.left)
.attr('x2',visWidth + margin.right + margin.left)
.attr('y1',populationScale(meanPopulation))
.attr('y2',populationScale(meanPopulation))
.attr('stroke-width',1)
.attr('stroke','green')

const meanText = svg.append('text')
.attr('x',margin.left + 100)
.attr('y',populationScale(meanPopulation) + 12)
.attr('fill','red')
.text(`Mean Population is ${d3.format('~s')(meanPopulation)}`)
//making lollipop on top of the bar chart
g.selectAll('circle')
.data(data).join('circle')
.attr('cx',d => countryScale(d.country) + countryScale.bandwidth()/ 2)
.attr('cy',d => populationScale(d.population))
.attr('r', 7)
.attr('fill','yellow')
.attr('id','lolli')
.attr('visibility',lolliplot)
//making lines on top of the bar chart for the lollipop
g.selectAll('line')
.data(data).join('line')
.attr('x1',d => countryScale(d.country) + countryScale.bandwidth()/ 2)
.attr('x2',d => countryScale(d.country) + countryScale.bandwidth()/ 2)
.attr('y1',d => populationScale(d.population))
.attr('y2',d => visHeight)
.attr('stroke','yellow')
.attr('id','lolli')
.attr('visibility',lolliplot)
// add a group for the y-axis
g.append('g')
.call(yAxis)
.call(g => g.select('.domain').remove());
// add a group for the x-axis
g.append('g')
// we have to move this group down to the bottom of the vis
.attr('transform', `translate(0, ${visHeight})`)
.call(xAxis)
.call(g => g.select('.domain').remove())
// add a label for the x-axis
.append('text')
.attr('fill', 'black')
.attr('font-family', 'sans-serif')
.attr('x', visWidth / 2)
.attr('y', 40)
.text("Population");
return svg.node();
}
Insert cell
yAxis = d3.axisLeft(populationScale).tickFormat(d3.format('~s'))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html`<div style='font-family: sans-serif; font-size: 10px; font-weight: bold;'>Diamond Cut</div>
${swatches({color})}`
Insert cell
diamondsChart
Insert cell
Insert cell
colorToCutToCount = d3.rollup(diamonds, g => g.length, d => d.color, d => d.cut)
Insert cell
colorToCutToCount.get("E").get("Fair")
Insert cell
[...colorToCutToCount.keys()]
Insert cell
groupBars =
Array.from(colorToCutToCount, (([color, map]) => {
map.set('count', d3.sum(map.values()));
map.set('cut', 1);
return Object.fromEntries(map)
[entries()]
Insert cell
[...groupBars.entries()]
Insert cell
Insert cell
diamondMargin = ({top: 10, bottom: 50, left: 85, right: 10})
Insert cell
diamondVisWidth = width - margin.left - margin.right
Insert cell
diamondVisHeight = 600 - margin.top - margin.bottom
Insert cell
Insert cell
Insert cell
diamondColors = [...new Set(diamonds.map(d => d.color))].sort()
Insert cell
Insert cell
groupX = d3.scaleBand()
.domain(diamondColors)
.range([0,diamondVisWidth])
.padding(0.1)
Insert cell
Insert cell
new Set(diamonds.map(d => d.cut))
Insert cell
diamondCuts = ['Premium', 'Ideal', 'Very Good', 'Good', 'Fair']
Insert cell
Insert cell
barX = d3.scaleBand()
.domain(diamondCuts)
.range([0,groupX.bandwidth()])
.padding(0.1)
Insert cell
Insert cell
d3.rollups(diamonds, g => g.length, d => d.color, d => d.cut).map(d => d[1].map(t => t[1]))
Insert cell
maxCount = d3.max(d3.flatRollup(diamonds, g => g.length, d => d.color, d => d.cut).map(d => d[2]))
Insert cell
Insert cell
y = d3.scaleLinear()
.domain([0,maxCount]).nice()
.range([diamondVisHeight,0])
Insert cell
Insert cell
color = d3.scaleOrdinal()
.domain(diamondCuts)
.range(['#bd0026', '#f03b20', '#fd8d3c', '#fecc5c', '#ffffb2'])
Insert cell
Insert cell
diamondXAxis = d3.axisBottom(groupX)
Insert cell
diamondYAxis = d3.axisLeft(y)
Insert cell
Insert cell
[...colorToCutToCount.entries()].map(([color, cutcount])=>({
mapColor : color,
mapCount : cutcount
}))
Insert cell
legend = html`<div style='font-family: sans-serif; font-size: 10px; font-weight: bold;'>Diamond Cut</div>
${swatches({color})}`
Insert cell
{
// set up
const svg = d3.create('svg')
.attr('width', diamondVisWidth + diamondMargin.left + diamondMargin.right)
.attr('height', diamondVisHeight + diamondMargin.top + diamondMargin.bottom);
const main = svg.append("g")
.attr('transform', `translate(${diamondMargin.left}, ${diamondMargin.top})`);
/*
Task A:
- add one g to main for each group of bars
- use colorToCutToCount as the data
- position each group using the groupX scale
*/

const groups = main.selectAll('g')
.data(colorToCutToCount)
.join('g')
.attr('transform',([color, cutToCount]) => `translate(${groupX(color)})`)
/*
Task B:
- add the bars to each group
- set the x, width, y, height, and fill attributes
*/
groups.selectAll('rect')
.data(([color,cutToCount]) => cutToCount)
.join('rect')
.attr('x', ([cut,Count]) =>barX(cut))
.attr('width',([cut,Count]) =>barX.bandwidth())
.attr('height',([cut,Count]) => diamondVisHeight - y(Count))
.attr('y',([cut,Count]) => y(Count))
.attr('fill',([cut,Count]) =>color(cut))

// add axes
main.append('g')
.attr('transform', `translate(0,${diamondVisHeight})`)
.call(diamondXAxis)
.call(g => g.select('.domain').remove())
.append('text')
.attr('x', diamondVisWidth / 2)
.attr('y', 30)
.attr('dominant-baseline', 'hanging')
.attr('text-align', 'middle')
.attr('fill', 'black')
.text('Diamond Color');
main.append('g')
.call(diamondYAxis)
.call(g => g.select('.domain').remove())
.append('text')
.attr('x', -50)
.attr('y', diamondVisHeight / 2)
.attr('dominant-baseline', 'middle')
.attr('text-align', 'end')
.attr('fill', 'black')
.text('Count')
return svg.node();
}
Insert cell
colorToCutToCount
Insert cell
Insert cell
Insert cell
Insert cell
import {swatches} from '@d3/color-legend'
Insert cell
Insert cell
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