Skip to content

Instantly share code, notes, and snippets.

@feyderm
Last active February 3, 2023 22:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save feyderm/6bdbc74236c27a843db633981ad22c1b to your computer and use it in GitHub Desktop.
Save feyderm/6bdbc74236c27a843db633981ad22c1b to your computer and use it in GitHub Desktop.
Scatter plot + Brush

Data is from the state data set.

Brush over points to reveal their values in an adjacent table.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
text {
font-family: sans-serif;
fill: #000000;
}
table {
visibility: hidden;
position: absolute;
top: 30px;
left: 500px;
font-family: sans-serif;
font-size: 0.7em;
}
tr:nth-child(even) {
background-color: #d9d9d9;
}
.brushed {
fill: #ff3399;
stroke: #8e1b54;
opacity: 1.0;
}
.non_brushed {
fill: #404040;
opacity: 0.5;
}
</style>
<body>
<!--viz-->
<div id="chart"></div>
<!--table for data of brushed elements-->
<div id="table">
<table>
<tr>
<th>State</th>
<th>Income</th>
<th>High School Graduation</th>
</tr>
</table>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript">
var margin = {top: 20, right: 0, bottom: 50, left: 85},
svg_dx = 500,
svg_dy = 400,
plot_dx = svg_dx - margin.right - margin.left,
plot_dy = svg_dy - margin.top - margin.bottom;
var x = d3.scaleLinear().range([margin.left, plot_dx]),
y = d3.scaleLinear().range([plot_dy, margin.top]);
var formatIncome = d3.format("$,"),
formatHsGrad = d3.format(".1%"),
formatHsGradAxis = d3.format(".0%");
var svg = d3.select("#chart")
.append("svg")
.attr("width", svg_dx)
.attr("height", svg_dy);
d3.csv("states.csv", d => {
var n = d.length;
var d_extent_x = d3.extent(d, d => +d.income),
d_extent_y = d3.extent(d, d => +d.hs_grad);
x.domain(d_extent_x);
y.domain(d_extent_y);
var axis_x = d3.axisBottom(x)
.tickFormat(formatIncome),
axis_y = d3.axisLeft(y)
.tickFormat(formatHsGradAxis);
svg.append("g")
.attr("id", "axis_x")
.attr("transform", "translate(0," + (plot_dy + margin.bottom / 2) + ")")
.call(axis_x);
svg.append("g")
.attr("id", "axis_y")
.attr("transform", "translate(" + (margin.left / 2) + ", 0)")
.call(axis_y);
d3.select("#axis_x")
.append("text")
.attr("transform", "translate(360, -10)")
.text("Per capita income (1974)");
d3.select("#axis_y")
.append("text")
.attr("transform", "rotate(-90) translate(-20, 15)")
.text("High-school graduates (1970)");
var circles = svg.append("g")
.selectAll("circle")
.data(d)
.enter()
.append("circle")
.attr("r", 5)
.attr("cx", (d) => x(+d.income))
.attr("cy", (d) => y(+d.hs_grad))
.attr("class", "non_brushed");
function highlightBrushedCircles() {
if (d3.event.selection != null) {
// revert circles to initial style
circles.attr("class", "non_brushed");
var brush_coords = d3.brushSelection(this);
// style brushed circles
circles.filter(function (){
var cx = d3.select(this).attr("cx"),
cy = d3.select(this).attr("cy");
return isBrushed(brush_coords, cx, cy);
})
.attr("class", "brushed");
}
}
function displayTable() {
// disregard brushes w/o selections
// ref: http://bl.ocks.org/mbostock/6232537
if (!d3.event.selection) return;
// programmed clearing of brush after mouse-up
// ref: https://github.com/d3/d3-brush/issues/10
d3.select(this).call(brush.move, null);
var d_brushed = d3.selectAll(".brushed").data();
// populate table if one or more elements is brushed
if (d_brushed.length > 0) {
clearTableRows();
d_brushed.forEach(d_row => populateTableRow(d_row))
} else {
clearTableRows();
}
}
var brush = d3.brush()
.on("brush", highlightBrushedCircles)
.on("end", displayTable);
svg.append("g")
.call(brush);
});
function clearTableRows() {
hideTableColNames();
d3.selectAll(".row_data").remove();
}
function isBrushed(brush_coords, cx, cy) {
var x0 = brush_coords[0][0],
x1 = brush_coords[1][0],
y0 = brush_coords[0][1],
y1 = brush_coords[1][1];
return x0 <= cx && cx <= x1 && y0 <= cy && cy <= y1;
}
function hideTableColNames() {
d3.select("table").style("visibility", "hidden");
}
function showTableColNames() {
d3.select("table").style("visibility", "visible");
}
function populateTableRow(d_row) {
showTableColNames();
var d_row_filter = [d_row.state,
formatIncome(d_row.income),
formatHsGrad(d_row.hs_grad)];
d3.select("table")
.append("tr")
.attr("class", "row_data")
.selectAll("td")
.data(d_row_filter)
.enter()
.append("td")
.attr("align", (d, i) => i == 0 ? "left" : "right")
.text(d => d);
}
</script>
</body>
state population income illiteracy life_exp murder hs_grad frost area
Alabama 3615 3624 2.1 69.05 15.1 0.413 20 50708
Alaska 365 6315 1.5 69.31 11.3 0.667 152 566432
Arizona 2212 4530 1.8 70.55 7.8 0.581 15 113417
Arkansas 2110 3378 1.9 70.66 10.1 0.399 65 51945
California 21198 5114 1.1 71.71 10.3 0.626 20 156361
Colorado 2541 4884 0.7 72.06 6.8 0.639 166 103766
Connecticut 3100 5348 1.1 72.48 3.1 0.56 139 4862
Delaware 579 4809 0.9 70.06 6.2 0.546 103 1982
Florida 8277 4815 1.3 70.66 10.7 0.526 11 54090
Georgia 4931 4091 2 68.54 13.9 0.406 60 58073
Hawaii 868 4963 1.9 73.6 6.2 0.619 0 6425
Idaho 813 4119 0.6 71.87 5.3 0.595 126 82677
Illinois 11197 5107 0.9 70.14 10.3 0.526 127 55748
Indiana 5313 4458 0.7 70.88 7.1 0.529 122 36097
Iowa 2861 4628 0.5 72.56 2.3 0.59 140 55941
Kansas 2280 4669 0.6 72.58 4.5 0.599 114 81787
Kentucky 3387 3712 1.6 70.1 10.6 0.385 95 39650
Louisiana 3806 3545 2.8 68.76 13.2 0.422 12 44930
Maine 1058 3694 0.7 70.39 2.7 0.547 161 30920
Maryland 4122 5299 0.9 70.22 8.5 0.523 101 9891
Massachusetts 5814 4755 1.1 71.83 3.3 0.585 103 7826
Michigan 9111 4751 0.9 70.63 11.1 0.528 125 56817
Minnesota 3921 4675 0.6 72.96 2.3 0.576 160 79289
Mississippi 2341 3098 2.4 68.09 12.5 0.41 50 47296
Missouri 4767 4254 0.8 70.69 9.3 0.488 108 68995
Montana 746 4347 0.6 70.56 5 0.592 155 145587
Nebraska 1544 4508 0.6 72.6 2.9 0.593 139 76483
Nevada 590 5149 0.5 69.03 11.5 0.652 188 109889
New Hampshire 812 4281 0.7 71.23 3.3 0.576 174 9027
New Jersey 7333 5237 1.1 70.93 5.2 0.525 115 7521
New Mexico 1144 3601 2.2 70.32 9.7 0.552 120 121412
New York 18076 4903 1.4 70.55 10.9 0.527 82 47831
North Carolina 5441 3875 1.8 69.21 11.1 0.385 80 48798
North Dakota 637 5087 0.8 72.78 1.4 0.503 186 69273
Ohio 10735 4561 0.8 70.82 7.4 0.532 124 40975
Oklahoma 2715 3983 1.1 71.42 6.4 0.516 82 68782
Oregon 2284 4660 0.6 72.13 4.2 0.6 44 96184
Pennsylvania 11860 4449 1 70.43 6.1 0.502 126 44966
Rhode Island 931 4558 1.3 71.9 2.4 0.464 127 1049
South Carolina 2816 3635 2.3 67.96 11.6 0.378 65 30225
South Dakota 681 4167 0.5 72.08 1.7 0.533 172 75955
Tennessee 4173 3821 1.7 70.11 11 0.418 70 41328
Texas 12237 4188 2.2 70.9 12.2 0.474 35 262134
Utah 1203 4022 0.6 72.9 4.5 0.673 137 82096
Vermont 472 3907 0.6 71.64 5.5 0.571 168 9267
Virginia 4981 4701 1.4 70.08 9.5 0.478 85 39780
Washington 3559 4864 0.6 71.72 4.3 0.635 32 66570
West Virginia 1799 3617 1.4 69.48 6.7 0.416 100 24070
Wisconsin 4589 4468 0.7 72.48 3 0.545 149 54464
Wyoming 376 4566 0.6 70.29 6.9 0.629 173 97203
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment