Public
Edited
Jan 5
1 fork
Insert cell
Insert cell
data = nbaPlayers
Insert cell
Insert cell
Insert cell
topScorers = nbaPlayers.slice()
.sort((a, b) => d3.descending(a.pts, b.pts))
.filter(player => player.pts >= 20)
Insert cell
{
// dimensions and set up

const margin = {top: 30, right: 10, bottom: 40, left: 125};
const width = 800;
const height = 700;
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height)
.attr('font-family', 'sans-serif');

// title
svg.append('text')
.attr('x', width / 2)
.attr('y', 5)
.attr('font-size', 14)
.attr('dominant-baseline', 'hanging')
.attr('text-anchor', 'middle')
.text('Top scorers in 2020-2021 NBA season by points per game')

// scales

const x = d3.scaleLinear()
.domain([0, d3.max(topScorers, d => d.pts)])
.range([margin.left, width - margin.right]);

const y = d3.scaleBand()
.domain(topScorers.map(d => d.name))
.range([margin.top, height - margin.bottom])
.padding(0.25);

// axis generators

const xAxis = d3.axisBottom(x);
const yAxis = d3.axisLeft(y).tickSizeOuter(0);

// draw bars

svg.selectAll('rect')
.data(topScorers)
.join('rect')
.attr('x', x(0))
.attr('y', d => y(d.name))
.attr('width', d => x(d.pts) - x(0))
.attr('height', d => y.bandwidth())
.attr('fill', 'steelblue');

// draw axes

svg.append('g')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(xAxis)
.call(g => g.select('.domain').remove())
.append('text')
.attr('x', width / 2)
.attr('y', 30)
.attr('fill', 'black')
.attr('text-anchor', 'center')
.text('points per game')

svg.append('g')
.attr('transform', `translate(${margin.left})`)
.call(yAxis);

return svg.node();
}
Insert cell
Insert cell
{
// dimensions and set up

const margin = {top: 40, right: 40, bottom: 40, left: 90};

const width = 600 + margin.left + margin.right;
const height = 600 + margin.top + margin.bottom;
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height)
.attr('font-family', 'sans-serif');

// title

svg.append('text')
.attr('x', width / 2)
.attr('y', 5)
.attr('font-size', 14)
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'hanging')
.text('NBA players height vs. weight');

// scales

const x = d3.scaleLinear()
.domain(d3.extent(nbaPlayers, d => d.weight)).nice()
.range([margin.left, width - margin.right]);

const y = d3.scaleLinear()
.domain(d3.extent(nbaPlayers, d => d.height)).nice()
.range([height - margin.bottom, margin.top]);

// axis generators

const xAxis = d3.axisBottom(x);
const yAxis = d3.axisLeft(y);

// draw axes and grid

// x-axis and vertical grid lines

svg.append('g')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(xAxis)
.call(
// add grid lines
g => g.selectAll('.tick line').clone()
.attr('y1', 0)
.attr('y2', -(height - margin.top - margin.bottom))
.attr('stroke', '#d3d3d3')
.attr('stroke-width', 1)
)
.call(g => g.select('.domain').remove())
.append('text')
.attr('x', width / 2)
.attr('y', 30)
.attr('fill', 'black')
.attr('text-anchor', 'center')
.text('weight (kg)');

// y-axis and horizontal grid lines
svg.append('g')
.attr('transform', `translate(${margin.left})`)
.call(yAxis)
.call(
// add grid lines
g => g.selectAll('.tick line').clone()
.attr('x1', 0)
.attr('x2', width - margin.right - margin.left)
.attr('stroke', '#d3d3d3')
.attr('stroke-width', 1)
)
.call(g => g.select('.domain').remove())
.append('text')
.attr('x', -35)
.attr('y', height / 2)
.attr('fill', 'black')
.attr('dominant-baseline', 'center')
.attr('text-anchor', 'end')
.text('height (cm)');

// draw circles

svg.selectAll('circle')
.data(nbaPlayers)
.join('circle')
.attr('cx', d => x(d.weight))
.attr('cy', d => y(d.height))
.attr('r', 3)
.attr('fill', 'steelblue')
.attr('fill-opacity', 0.65);

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