D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
hdickie
Full window
Github gist
Scatterplot Matrix
Built with
blockbuilder.org
<!DOCTYPE html> <style> svg { font-size:14; padding: 4px; } line { stroke: lightgrey } circle { fill-opacity: .2; } rect { fill-opacity: .2; } </style> <body> <svg width = "960" height = "765" id = "vis1"></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> var svg = d3.select("#vis1"), margin = {top: 20, right: 20, bottom: 80, left: 50}, width = svg.attr("width") - margin.left - margin.right, height = svg.attr("height") - margin.top - margin.bottom, g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //Title svg.append("text") .attr("y",15) .style("font-size",24) .text("Mobility Colored by Quality of Schooling"); //predictor labels svg.append("text") .attr("transform","translate(20,110) rotate(-90)") .text("K Q5"); svg.append("text") .attr("transform","translate(20,240) rotate(-90)") .text("K Q4"); svg.append("text") .attr("transform","translate(20,375) rotate(-90)") .text("K Q3"); svg.append("text") .attr("transform","translate(20,510) rotate(-90)") .text("K Q2"); svg.append("text") .attr("transform","translate(20,635) rotate(-90)") .text("K Q1"); svg.append("text") .attr("transform","translate(115,715)") .text("Par Q1"); svg.append("text") .attr("transform","translate(285,715)") .text("Par Q2"); svg.append("text") .attr("transform","translate(465,715)") .text("Par Q3"); svg.append("text") .attr("transform","translate(645,715)") .text("Par Q4"); svg.append("text") .attr("transform","translate(825,715)") .text("Par Q5"); svg.append("text") .attr("transform","translate(0,730)") .style("font-size",15) .style("stroke","#000000") .text("Tier Name"); var squareSide = 15; var topRowSquare = 735; var btmRowSquare = 755; var hTextOffset = 19; var vTextOffset = 12; var entryOffset = 165; //relationship between square and text is (+19,+12) //lengend svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate(0,"+topRowSquare+")") .style("fill","#f70000"); svg.append("text") .attr("transform","translate("+hTextOffset+","+(topRowSquare + vTextOffset) +")") .style("font-size",14) .text("Less than two-year sch...") svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate(0,"+btmRowSquare+")") .style("fill","#ff3256"); svg.append("text") .attr("transform","translate("+hTextOffset+","+(btmRowSquare + vTextOffset) +")") .style("font-size",14) .text("Two-year for-profit") // svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset+","+topRowSquare+")") .style("fill","#ff3256"); svg.append("text") .attr("transform","translate("+(hTextOffset + entryOffset)+","+(topRowSquare + vTextOffset) +")") .style("font-size",14) .text("Two-year (public and p...)") svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset+","+btmRowSquare+")") .style("fill","#fff832"); svg.append("text") .attr("transform","translate("+(hTextOffset+entryOffset)+","+(btmRowSquare + vTextOffset) +")") .style("font-size",14) .text("Nonselective four-year...") // svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*2+","+topRowSquare+")") .style("fill","#fff832"); svg.append("text") .attr("transform","translate("+(hTextOffset + entryOffset*2)+","+(topRowSquare + vTextOffset) +")") .style("font-size",14) .text("Four-year for-profit") svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*2+","+btmRowSquare+")") .style("fill","#fff832"); svg.append("text") .attr("transform","translate("+(hTextOffset+entryOffset*2)+","+(btmRowSquare + vTextOffset) +")") .style("font-size",14) .text("Nonselective four-year...") // svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*3+","+topRowSquare+")") .style("fill","#007a0a"); svg.append("text") .attr("transform","translate("+(hTextOffset + entryOffset*3)+","+(topRowSquare + vTextOffset) +")") .style("font-size",14) .text("Selective private") svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*3+","+btmRowSquare+")") .style("fill","#007a0a"); svg.append("text") .attr("transform","translate("+(hTextOffset+entryOffset*3)+","+(btmRowSquare + vTextOffset) +")") .style("font-size",14) .text("Selective public") // svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*4+","+topRowSquare+")") .style("fill","#19cdff"); svg.append("text") .attr("transform","translate("+(hTextOffset + entryOffset*4)+","+(topRowSquare + vTextOffset) +")") .style("font-size",14) .text("Highly selective private") svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*4+","+btmRowSquare+")") .style("fill","#19cdff"); svg.append("text") .attr("transform","translate("+(hTextOffset+entryOffset*4)+","+(btmRowSquare + vTextOffset) +")") .style("font-size",14) .text("Highly selective public") // svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*5+","+topRowSquare+")") .style("fill","#2927aa"); svg.append("text") .attr("transform","translate("+(hTextOffset + entryOffset*5)+","+(topRowSquare + vTextOffset) +")") .style("font-size",14) .text("Ivy Plus") svg.append("rect") .attr("width",squareSide) .attr("height",squareSide) .attr("transform","translate("+entryOffset*5+","+btmRowSquare+")") .style("fill","#2927aa"); svg.append("text") .attr("transform","translate("+(hTextOffset+entryOffset*5)+","+(btmRowSquare + vTextOffset) +")") .style("font-size",14) .text("Other elite schools") d3.csv("hw2data.csv", function(error, data) { if (error) throw error; //grabs only the numeric vars we're plotting var nums = d3.keys(data[0]).filter(function(d){ return d != "" & d != "name" & d != "tier_name" & d != "Color"; }) var domainByPredictor = {}; nums.forEach(function(nums){ domainByPredictor[nums] = d3.extent(data, function(d){ return d[nums]; }); }); //coerce data.forEach(function(d){ d.k_q1 = +d.k_q1; d.k_q2 = +d.k_q2; d.k_q3 = +d.k_q3; d.k_q4 = +d.k_q4; d.k_q5 = +d.k_q5; d.par_q1 = +d.par_q1; d.par_q2 = +d.par_q2; d.par_q3 = +d.par_q3; d.par_q4 = +d.par_q4; d.par_q5 = +d.par_q5; }); var kids = ["k_q1","k_q2","k_q3","k_q4","k_q5"]; var pars = ["par_q1","par_q2","par_q3","par_q4","par_q5"]; var plotWidth = (width)/5; var plotHeight = (height)/5; var hz = [], vt = []; var padding = 4; //create mapping from data to plot for (i = 0 ; i < 5 ; ++i ){ hz.push(d3.scaleLinear() .domain(domainByPredictor[kids[i]]) .range([margin.left + plotWidth*i, margin.left + plotWidth*(i+1) - padding])); } for (i = 0 ; i < 5 ; ++i ){ vt.push(d3.scaleLinear() .domain(domainByPredictor[pars[i]]) .range([height - plotHeight*i + margin.top, height - plotHeight*(i + 1) + margin.top + padding])); } //draw axes svg.selectAll(".x.axis") .data(pars) .enter() .each(function(d, i) { svg.append("g") .attr("class", "axis axis--x") .attr("transform", "translate("+0+"," + (height + margin.top) + ")") .call(d3.axisBottom(hz[i]).ticks(4).tickSize(-height + padding)); }); svg.selectAll(".y.axis") .data(pars) .enter() .each(function(d, i) { svg.append("g") .attr("class", "axis axis--y") .attr("transform", "translate("+margin.left+"," + 0 + ")") .call(d3.axisLeft(vt[i]).ticks(4).tickSize(-width + padding)); }); //plot by subplot var cell = svg.selectAll(".cell") .data(cross(pars, kids)) .enter().append("g") .attr("class", "cell") .each(plot); //here, p contains i, j and the names of those corresp. vars x and y function plot(p) { var cell = d3.select(this); hz[p.i].domain(domainByPredictor[p.x]); vt[p.j].domain(domainByPredictor[p.y]); cell.selectAll("circle") .data(data) .enter().append("circle") .attr("cx", function(d) { return hz[p.i](d[p.x]); }) .attr("cy", function(d) { return vt[p.j](d[p.y]); }) .attr("r", 4) .style("fill", function(d) { return d.Color; }); } }); //used to obtain desired variables for subplots function cross(a, b) { var c = [], i, j; for (i = -1; ++i < 5;) for (j = -1; ++j < 5;) c.push({x: a[i], i: i, y: b[j], j: j}); return c; } </script> </body>
https://d3js.org/d3.v4.min.js