import { select, scaleLinear, max, axisLeft, axisBottom, }
from 'd3'; const svg = select('svg'); const width =
+svg.attr('width'); const height = +svg.attr('height');
const render = (data) => { const title = 'Age vs. Income
Scatterplot'; const xValue = d => d.Age; const xAxisLabel =
'Age'; const yValue = d => d.Income; const yAxisLabel =
'Income'; const margin = { top: 60, right: 40, bottom: 88,
left: 105 }; const innerWidth = width - margin.left -
margin.right; const innerHeight = height - margin.top -
margin.bottom; const xScale = scaleLinear() .domain([0,
max(data, xValue)]) .range([0, innerWidth]) .nice(); const
yScale = scaleLinear() .domain([0, max(data, yValue)])
.range([innerHeight, 0]) .nice(); const g = svg.append('g')
.attr('transform',
`translate(${margin.left},${margin.top})`); const xAxis =
axisBottom(xScale) .tickSize(-innerHeight) .tickPadding(15);
const yAxis = axisLeft(yScale) .tickSize(-innerWidth)
.tickPadding(10); const yAxisG = g.append('g').call(yAxis);
yAxisG.selectAll('.domain').remove(); yAxisG.append('text')
.attr('class', 'axis-label') .attr('y', -60) .attr('x',
-innerHeight / 2) .attr('fill', 'black') .attr('transform',
'rotate(-90)') .attr('text-anchor', 'middle')
.text(yAxisLabel); const xAxisG = g.append('g').call(xAxis)
.attr('transform', `translate(0,${innerHeight})`);
xAxisG.select('.domain').remove(); xAxisG.append('text')
.attr('class', 'axis-label') .attr('y', 75) .attr('x',
innerWidth / 2) .attr('fill', 'black') .text(xAxisLabel);
g.selectAll('circle').data(data) .enter().append('circle')
.attr('cy', d => yScale(yValue(d))) .attr('cx', d =>
xScale(xValue(d))) .attr('r', 5); svg.append('text')
.attr('class', 'title') .attr('x', width / 2) .attr('y', 40)
.attr('text-anchor', 'middle') .text(title); };