This gist walks the user through a scatter plot and set of lines and text based on csv data
Last active
May 21, 2018 01:32
-
-
Save delgadom/7fe6b33276fb4aca80656a5541a05988 to your computer and use it in GitHub Desktop.
simple econometric walkthrough
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<!-- Load D3 from site --> | |
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script> | |
<link rel="stylesheet" href="scatter.css"></style> | |
</head> | |
<!-- CSS (Styling) --> | |
<!-- End CSS (Styling) --> | |
<body> | |
<h4>Next step</h4> | |
<h3></h3 | |
<!-- Begin D3 Javascript --> | |
<script type="text/javascript" src="scatter.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
step | line | point | x | y | w | color | |
---|---|---|---|---|---|---|---|
1 | 0 | 0 | 20 | 60 | 1 | black | |
1 | 0 | 1 | 140 | 95 | 1 | black | |
2 | 0 | 0 | 5 | 72 | 1 | blue | |
2 | 0 | 1 | 60 | 100 | 1 | blue | |
2 | 1 | 0 | 40 | 170 | 1 | green | |
2 | 1 | 1 | 90 | 135 | 1 | green | |
2 | 2 | 0 | 155 | 65 | 1 | red | |
2 | 2 | 1 | 190 | 90 | 1 | red | |
3 | 0 | 0 | 35 | 10 | 1 | blue | |
3 | 0 | 1 | 55 | 70 | 1 | blue | |
3 | 1 | 0 | 70 | 15 | 1 | green | |
3 | 1 | 1 | 85 | 60 | 1 | green | |
3 | 2 | 0 | 112 | 65 | 1 | red | |
3 | 2 | 1 | 120 | 90 | 1 | red | |
4 | 0 | 0 | 250 | 80 | 1 | red | |
4 | 0 | 1 | 393 | 47 | 1 | red | |
4 | 0 | 2 | 467 | 63 | 1 | red | |
4 | 1 | 0 | 7 | 137 | 1 | blue | |
4 | 1 | 1 | 120 | 91 | 1 | blue | |
4 | 1 | 2 | 212 | 73 | 1 | blue | |
4 | 2 | 0 | 340 | 111 | 1 | green | |
4 | 2 | 1 | 473 | 92 | 1 | green | |
4 | 2 | 2 | 589 | 149 | 1 | green | |
4 | 3 | 0 | 50 | 130 | 3 | black | |
4 | 3 | 1 | 250 | 70 | 3 | black | |
4 | 3 | 2 | 500 | 110 | 3 | black | |
5 | 0 | 0 | 15 | 70 | 1 | red | |
5 | 0 | 1 | 30 | 50 | 1 | red | |
5 | 0 | 2 | 62 | 84 | 1 | red | |
5 | 1 | 0 | 80 | 130 | 1 | blue | |
5 | 1 | 1 | 90 | 130 | 1 | blue | |
5 | 1 | 2 | 126 | 110 | 1 | blue | |
5 | 2 | 0 | 122 | 20 | 1 | green | |
5 | 2 | 1 | 130 | 50 | 1 | green | |
5 | 2 | 2 | 157 | 80 | 1 | green |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
step | x | y | r | color | |
---|---|---|---|---|---|
0 | 30 | 50 | 2 | black | |
0 | 15 | 70 | 2 | black | |
0 | 62 | 84 | 2 | black | |
0 | 80 | 130 | 4 | black | |
0 | 126 | 110 | 4 | black | |
0 | 90 | 130 | 4 | black | |
0 | 130 | 50 | 1 | black | |
0 | 157 | 80 | 1 | black | |
0 | 122 | 20 | 1 | black | |
1 | 30 | 50 | 2 | red | |
1 | 15 | 70 | 2 | red | |
1 | 62 | 84 | 2 | red | |
1 | 80 | 130 | 4 | blue | |
1 | 126 | 110 | 4 | blue | |
1 | 90 | 130 | 4 | blue | |
1 | 130 | 50 | 1 | green | |
1 | 157 | 80 | 1 | green | |
1 | 122 | 20 | 1 | green | |
2 | 150 | 80 | 8 | red | |
2 | 167 | 63 | 8 | red | |
2 | 193 | 97 | 8 | red | |
2 | 20 | 61 | 2 | blue | |
2 | 1 | 73 | 2 | blue | |
2 | 57 | 97 | 2 | blue | |
2 | 40 | 171 | 8 | green | |
2 | 73 | 132 | 8 | green | |
2 | 89 | 149 | 8 | green | |
3 | 110 | 71 | 2 | red | |
3 | 116 | 90 | 2 | red | |
3 | 119 | 68 | 2 | red | |
3 | 43 | 9 | 2 | blue | |
3 | 48 | 62 | 2 | blue | |
3 | 41 | 37 | 2 | blue | |
3 | 73 | 25 | 8 | green | |
3 | 79 | 43 | 8 | green | |
3 | 77 | 32 | 8 | green | |
4 | 250 | 80 | 1 | red | |
4 | 467 | 63 | 1 | red | |
4 | 393 | 47 | 1 | red | |
4 | 120 | 91 | 1 | blue | |
4 | 212 | 73 | 1 | blue | |
4 | 7 | 137 | 1 | blue | |
4 | 340 | 111 | 1 | green | |
4 | 473 | 92 | 1 | green | |
4 | 589 | 149 | 1 | green | |
5 | 30 | 50 | 2 | red | |
5 | 15 | 70 | 2 | red | |
5 | 62 | 84 | 2 | red | |
5 | 80 | 130 | 4 | blue | |
5 | 126 | 110 | 4 | blue | |
5 | 90 | 130 | 4 | blue | |
5 | 130 | 50 | 1 | green | |
5 | 157 | 80 | 1 | green | |
5 | 122 | 20 | 1 | green |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Format X and Y Axis */ | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-family: sans-serif; | |
font-size: 11px; | |
} | |
.regression-line { | |
fill: none; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var current_index = 0; | |
var sorted_points = []; | |
var sorted_lines = []; | |
var sorted_text = []; | |
var max_steps = 1; | |
// Setup settings for graphic | |
var canvas_width = 600; | |
var canvas_height = 300; | |
var padding_horiz = 70; // for chart edges | |
var padding_vert = 30; // for chart edges | |
// initialize scale functions | |
var xScale = d3.scaleLinear().domain([0, 1]).range([padding_horiz, canvas_width - padding_horiz * 2]); | |
var yScale = d3.scaleLinear().domain([0, 1]).range([canvas_height - padding_vert, padding_vert]); | |
var zScale = d3.scaleLinear().domain([0, 1]).range([1, 8]); | |
// Define X axis | |
var xAxis = d3.axisBottom(xScale); | |
// Define Y axis | |
var yAxis = d3.axisLeft(yScale); | |
// Create SVG element | |
var svg = d3.select("h3") // This is where we put our vis | |
.append("svg") | |
.attr("width", canvas_width) | |
.attr("height", canvas_height) | |
var line = d3.line() | |
.x(function(d) { return xScale(Number(d.x)); }) | |
.y(function(d) { return yScale(Number(d.y)); }) | |
.curve(d3.curveMonotoneX); | |
var initialize_points = function(points_dataset) { | |
points_dataset.forEach(function(elem) { | |
elem.step = Number(elem.step); | |
elem.x = Number(elem.x); | |
elem.y = Number(elem.y); | |
elem.r = Number(elem.r); | |
}); | |
points_dataset.forEach(function(elem) { | |
while (Number(elem['step']) >= sorted_points.length - 1) { | |
sorted_points.push(new Array()); | |
} | |
sorted_points[Number(elem['step'])].push(elem); | |
}); | |
// update max steps with length of sorted_points | |
if (sorted_points.length > max_steps) { | |
max_steps = sorted_points.length; | |
}; | |
// Setup data | |
var dataset = sorted_points[0]; // Initialize empty array | |
// Create scale functions | |
xScale.domain([0, d3.max(dataset, function(d) { | |
return d['x']; // input domain | |
})]) | |
.range([padding_horiz, canvas_width - padding_horiz * 2]); // output range | |
yScale.domain([0, d3.max(dataset, function(d) { | |
return d['y']; // input domain | |
})]) | |
.range([canvas_height - padding_vert, padding_vert]); // remember y starts on top going down so we flip | |
zScale.domain([0, d3.max(dataset, function(d) { | |
return d['r']; // input domain | |
})]) | |
.range([1, 8]); // remember z starts on top going down so we flip | |
// Define X axis | |
d3.axisBottom(xScale) | |
.ticks(5); | |
// Define Y axis | |
d3.axisLeft(yScale) | |
.ticks(5); | |
// Create Circles | |
svg.selectAll("circle") | |
.data(dataset) | |
.enter() | |
.append("circle") // Add circle svg | |
.attr("cx", function(d) { | |
return xScale(d['x']); // Circle's X | |
}) | |
.attr("cy", function(d) { // Circle's Y | |
return yScale(d['y']); | |
}) | |
.attr("r", function(d) { | |
return zScale(d['r']); | |
}) // radius | |
.attr("fill", function(d) { | |
return d['color']; | |
}); // Change color | |
// Add to X axis | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + (canvas_height - padding_vert) +")") | |
.call(xAxis); | |
// Add to Y axis | |
svg.append("g") | |
.attr("class", "y axis") | |
.attr("transform", "translate(" + padding_horiz +",0)") | |
.call(yAxis); | |
} | |
var initialize_lines = function(lines_dataset) { | |
lines_dataset.forEach(function(elem) { | |
elem.point = Number(elem.point); | |
elem.line = Number(elem.line); | |
elem.step = Number(elem.step); | |
elem.x = Number(elem.x); | |
elem.y = Number(elem.y); | |
elem.w = Number(elem.w); | |
}); | |
lines_dataset.forEach(function(elem) { | |
while (Number(elem['step']) >= sorted_lines.length) { | |
sorted_lines.push(new Array()); | |
} | |
sorted_lines[Number(elem['step'])].push(elem); | |
}); | |
// update max steps with length of sorted_lines | |
if (sorted_lines.length > max_steps) { | |
max_steps = sorted_lines.length; | |
}; | |
var lines = []; | |
if (sorted_lines[current_index] !== undefined) { | |
sorted_lines[0].forEach(function(elem) { | |
while (Number(elem['line']) >= lines.length - 1) { | |
lines.push(new Array()); | |
}; | |
lines[Number(elem['line'])].push(elem); | |
}); | |
lines.forEach(function(l) { | |
svg.append("path") | |
.data(l) | |
.attr("class", "regression-line") | |
.attr("stroke", function(d) { return d.color }) | |
.attr("d", line(l) | |
)}); | |
}; | |
} | |
var initialize_text = function(text_dataset) { | |
text_dataset.forEach(function(elem) { | |
elem.step = Number(elem.step); | |
elem.x = Number(elem.x); | |
elem.y = Number(elem.y); | |
elem.font_size = Number(elem.font_size); | |
}); | |
text_dataset.forEach(function(elem) { | |
while (Number(elem['step']) >= sorted_text.length - 1) { | |
sorted_text.push(new Array()); | |
} | |
sorted_text[Number(elem['step'])].push(elem); | |
}); | |
// update max steps with length of sorted_text | |
if (sorted_text.length > max_steps) { | |
max_steps = sorted_text.length; | |
}; | |
updateText(); | |
} | |
var updateLines = function() { | |
// Update lines | |
var lines = []; | |
if (sorted_lines[current_index] !== undefined) { | |
sorted_lines[current_index].forEach(function(elem) { | |
while (Number(elem['line']) >= lines.length - 1) { | |
lines.push(new Array()); | |
}; | |
lines[Number(elem['line'])].push(elem); | |
}); | |
lines.forEach(function(l) { | |
svg.append("path") | |
.data(l) | |
.attr("class", "regression-line") | |
.attr("stroke", function(d) { return d.color }) | |
.attr("d", line(l) | |
)}); | |
}; | |
} | |
var updateText = function() { | |
svg.selectAll('text') | |
.filter('.text-label') | |
.remove(); | |
setTimeout(function() { | |
if (sorted_text[current_index] !== undefined) { | |
sorted_text[current_index].forEach(function(elem) { | |
svg.append("text") | |
.attr("class", "p text-label") | |
.attr("x", xScale(elem['x'])) | |
.attr("y", yScale(elem['y'])) | |
.text(elem['text']) | |
.attr('font-size', elem['font-size']) | |
.attr('text-anchor', elem['text-anchor']) | |
.attr('fill', elem['color']) | |
}); | |
} | |
}, 1000); | |
} | |
var step_through_animation = function() { | |
current_index = (current_index + 1) % sorted_points.length; | |
var dataset = sorted_points[current_index]; | |
// Update scale domains | |
xScale.domain([0, d3.max(dataset, function(d) { | |
return d['x']; })]); | |
yScale.domain([0, d3.max(dataset, function(d) { | |
return d['y']; })]); | |
zScale.domain([0, d3.max(dataset, function(d) { | |
return d['r']; })]); | |
svg.selectAll('path') | |
.transition() | |
.duration(100) | |
.remove(); | |
// Update circles | |
svg.selectAll("circle") | |
.data(dataset) // Update with new data | |
.transition() // Transition from old to new | |
.duration(1000) // Length of animation | |
.delay(function(d, i) { | |
return i / dataset.length * 500; // Dynamic delay (i.e. each item delays a little longer) | |
}) | |
//.ease("linear") // Transition easing - default 'variable' (i.e. has acceleration), also: 'circle', 'elastic', 'bounce', 'linear' | |
.attr("cx", function(d) { | |
return xScale(d['x']); // Circle's X | |
}) | |
.attr("cy", function(d) { | |
return yScale(d['y']); // Circle's Y | |
}) | |
.attr("r", function(d) { | |
return zScale(d['r']); // Circle's size | |
}) | |
.attr("fill", function(d) { | |
return d['color']; | |
}) // Change color; | |
.on("end", updateLines) | |
// Update X Axis | |
svg.select(".x.axis") | |
.transition() | |
.duration(1000) | |
.call(xAxis); | |
// Update Y Axis | |
svg.select(".y.axis") | |
.transition() | |
.duration(1000) | |
.call(yAxis); | |
updateText(); | |
} | |
d3.csv("points.csv", function(points_dataset) { | |
initialize_points(points_dataset); | |
}); | |
d3.csv("lines.csv", function(lines_dataset) { | |
initialize_lines(lines_dataset); | |
}); | |
d3.csv("text.csv", function(text_dataset) { | |
initialize_text(text_dataset); | |
}); | |
// On click, update with new data | |
d3.select("h4").on("click", function() { | |
step_through_animation(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
step | x | y | font-size | color | text-anchor | text | |
---|---|---|---|---|---|---|---|
1 | 110 | 100 | 10 | black | end | simple linear regression on all points | |
2 | 100 | 120 | 14 | black | start | this is another piece of text | |
3 | 35 | 50 | 12 | blue | center | i1 | |
3 | 65 | 40 | 12 | green | center | i2 | |
3 | 103 | 80 | 12 | red | center | i3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment