-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscatter-plot.js
109 lines (95 loc) · 3.51 KB
/
scatter-plot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// adapted from Michele Weigle's block here: http://bl.ocks.org/weiglemc/6185069
// and from Chris Tuft's block here: https://bl.ocks.org/ctufts/298bfe4b11989960eeeecc9394e9f118
function scatterPlot(data, regressionLine, seriesNames) {
const margin = { top: 20, right: 20, bottom: 40, left: 40 };
const height = 400;
const width = 600;
const xScale = d3.scaleLinear().range([0, width]);
const xAxis = d3.axisBottom(xScale);
const yScale = d3.scaleLinear().range([height, 0]);
const yAxis = d3.axisLeft(yScale);
const getX = (d) => d.x;
const getY = (d) => d.y;
const posX = (d) => xScale(getX(d));
const posY = (d) => yScale(getY(d));
const titleCase = (text) => `${text.slice(0, 1).toUpperCase()}${text.slice(1).toLowerCase()}`;
const midEastRed = '#EABA6B';
const spiro = '#2DC7FF';
var svg = d3.select('#regression-plot')
.attr('class', 'results__chart')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
var tooltip = d3.select('body').append('div')
.attr('class', 'results__tooltip')
.style('opacity', 0);
const xMax = d3.max(data, getX);
xScale.domain([d3.min(data, getX) - 1, xMax + 1]);
yScale.domain([d3.min(data, getY) - 1, d3.max(data, getY) + 1]);
const regressionPoints = {
x1: xScale(margin.right),
x2: xScale(xMax),
y1: yScale(regressionLine.intercept),
y2: yScale((xMax * regressionLine.slope) + regressionLine.intercept),
};
svg.append('g')
.attr('class', 'x axis')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
.append('text')
.attr('class', 'label')
.attr('x', width / 2)
.attr('y', 30)
.style('text-anchor', 'center')
.text(titleCase(seriesNames.x))
.style('fill', 'black');
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.attr('class', 'label')
.attr('transform', 'rotate(-90)')
.attr('y', -30)
.attr('x', -(width / 3))
.style('text-anchor', 'center')
.text(titleCase(seriesNames.y))
.style('fill', 'black');
svg.append('g')
.attr('class', 'dots')
.selectAll('.dot')
.data(data)
.enter()
.append('circle')
.attr('class', 'dot')
.attr('r', 3.5)
.attr('cx', posX)
.attr('cy', posY)
.style('fill', midEastRed)
.style('stroke', 'black')
.style('stroke-width', 1)
.on('mouseover', (d) => {
tooltip.transition()
.duration(200)
.style('opacity', .9);
tooltip.html(`${titleCase(seriesNames.x)}: ${d.x}<br />${titleCase(seriesNames.y)}: ${d.y}`)
.style('left', `${(d3.event.pageX + 5)}px`)
.style('top', `${(d3.event.pageY - 28)}px`);
})
.on('mouseout', (d) => {
tooltip.transition()
.duration(500)
.style('opacity', 0);
});
svg.append('g')
.attr('class', 'line')
.append('line')
.datum(data)
.attr('class', 'reg-line')
.attr('x1', regressionPoints.x1)
.attr('x2', regressionPoints.x2)
.attr('y1', regressionPoints.y1)
.attr('y2', regressionPoints.y2)
.attr('stroke', 'red')
.attr('stroke-width', 2);
}