Skip to content

Instantly share code, notes, and snippets.

@derPlau
Last active October 8, 2018 10:50
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save derPlau/8642419 to your computer and use it in GitHub Desktop.
d3 Bubble Chart: Industry/Occupation Cluster Matrix

My first foray into d3.js. This variant of a bubble-chart adapts the bubble concept to a tabular format. In this case, (simulated) Wisconsin employment in major industry groups and skills-based occupational clusters is shown depicted to order-of-magnitude approximation. A glance at a row gives an idea of the overall importance of an industry to employment (so extraction industries like mining have relatively low employment; Health & Social Service industries have relatively high employment); a glance at a column gives a similar picture of employment by occupation. A deeper look reveals detailed patterns of employment: the manufacturing industry employs primarily Equipment Operations & General Physical Labor occupations; Clerical occupations are employed at a modest level in most industries, but disproportionately large levels in Finance and Health/Social Services.

Industry Clerks Communication Construction Engineering Equip Op Repair Food Svc Gen Phys Health & Bio Hum & Ed Analysis Managers Outreach Public safety Service
Government 3 2 2 2 3 2 2 3 3 3 3 3 3 3 2
Other Svcs 3 2 2 1 3 2 3 3 2 2 2 3 3 1 3
Accom/Food 3 1 1 1 3 1 4 3 1 1 1 3 1 1 4
Arts/Ent/Rec 2 2 1 1 2 1 3 2 1 2 2 2 3 1 3
Health/Soc 4 2 1 1 3 1 3 2 4 3 2 3 4 2 3
Ed Svcs 3 3 1 1 3 1 3 2 3 4 3 3 3 1 3
Admin/Waste 3 2 1 2 2 1 2 2 2 1 3 3 1 1 2
Mgmt 3 2 1 2 2 1 2 2 2 1 2 2 1 1 2
Prof/Sci/Tech 3 2 1 3 2 1 1 2 2 1 3 3 2 1 2
Real Estate 3 1 1 1 2 1 2 2 1 1 2 2 1 1 2
Finance 4 1 1 1 1 1 2 1 2 1 3 3 1 1 2
Information 3 3 1 1 2 2 2 2 1 2 3 3 1 1 2
Transport 3 1 1 1 3 1 2 3 1 1 2 3 2 1 3
Retail 3 1 2 1 3 2 4 3 2 1 2 3 3 1 4
Wholesale 3 2 1 2 3 2 2 3 1 1 3 3 1 1 3
Manufacturing 3 2 2 3 4 3 3 4 2 1 3 3 1 1 3
Construction 3 1 3 2 3 3 1 3 1 1 2 3 1 1 1
Utilities 2 1 2 1 2 1 1 2 1 1 2 2 1 1 1
Extraction 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1
Agriculture 2 1 1 1 2 1 2 3 1 1 1 1 1 1 2
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.grow rect {
stroke: black;
shape-rendering: crispEdges;
fill: none;
}
.axis text {
font: 10px sans-serif;
}
.legend text {
font: 12px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path,
.x.axis line {
display: none;
}
.y.axis path,
.y.axis line {
display: none;
}
</style>
<svg class="chart"></svg>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var totWidth = 700,
totHeight = totWidth * 1.2,
margin = {top: 80, right: 30, bottom: 80, left: 80},
width = totWidth - (margin.left + margin.right),
height = totHeight - (margin.top + margin.bottom);
var x = d3.scale.ordinal()
.rangeRoundBands([0, width]);
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("top");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var chart = d3.select(".chart")
.attr("width", totWidth)
.attr("height", totHeight)
.append("g")
.attr("transform","translate("+margin.left+","+margin.top+")");
d3.tsv("igmat.tsv"/*, type*/, function(error, data) {
var grpNames = d3.keys(data[0]).filter(function(key) { return key !== "Industry"; });
data.forEach(function(d) {
d.groups = grpNames.map(function(name) { return {name: name, value: +d[name]}; });
});
y.domain(data.map(function(d) { return d.Industry; }));
var allcols = Object.keys(data[0]),
cols = allcols.slice(1,allcols.length);
x.domain(grpNames);
chart.append("g")
.attr("class","x axis")
.attr("transform","translate(0,0)")
.call(xAxis)
.selectAll("text")
.style("text-anchor","start")
.attr("transform","rotate(-90)")
.attr("dx","0.5em")
.attr("dy",x.rangeBand()/2-10)
;
chart.append("g")
.attr("class","y axis")
.call(yAxis)
;
var grows = chart.selectAll(".grow")
.data(data)
.enter().append("g")
.attr("class","grow")
.attr("transform", function(d) { return "translate(0," + y(d.Industry) + ")"; })
;
var gcells = grows.selectAll(".gcell")
.data(function(d) { return d.groups; })
.enter() .append("g")
.attr("transform", function(d,i,j) {return "translate(" + i*x.rangeBand() + ",0)" ; } )
.attr("class","gcell")
;
gcells
.append("rect")
.attr("x",0)
.attr("y",0)
.attr("height",y.rangeBand())
.attr("width",x.rangeBand())
.style("fill-opacity",1)
.style("fill", function(d,i,j) {
if ((i % 2 != 0 && j % 2 == 0))
{return "#dddddd";}
else if (i % 2 != 0 || j % 2 == 0)
{return "#eeeeee";}
else
{return "#ffffff";}
}
)
;
rmax = Math.min(y.rangeBand()/2-4,x.rangeBand()/2-4)
gcells.append("circle")
.attr("cy",y.rangeBand()/2)
.attr("cx",x.rangeBand()/2)
.attr("r", function(d) {
var rind = d.value;
return rmax / ((-1)*(rind - 5));
}
)
.style("fill", function(d) {
var gbval = 1+Math.floor(255 - (255/4*(d.value-1)));
return "rgb(" + 255 + "," + gbval + "," + gbval + ")";
}
)
.style("stroke","black")
;
var legend = chart
.append("g")
.attr("transform", "translate(0," + (height + 0) + ")")
.attr("class","legend")
.style("font-weight","bold")
;
var legwidths = [0,55,135,235];
var legsymbols = legend.selectAll(".legsymbols")
.data(["0-500","500-5,000","5,000-50,000",">50,000"])
.enter()
.append("g")
.attr("class","legsymbols")
.attr("transform",function(d,i) {return "translate(" + (150 + legwidths[i]) + ",0)";})
;
var legendspace = 5;
legsymbols.append("circle")
.attr("cx", function(d,i) {return rmax / ((-1)*((i+1) - 5)) ;})
.attr("cy", function(d,i) {return (legendspace+2*rmax) - (rmax / ((-1)*((i+1) - 5))) ;})
.style("fill", function(d,i) {
var gbval = 1+Math.floor(255 - (255/4*((i+1)-1)));
return "rgb(" + 255 + "," + gbval + "," + gbval + ")";
}
)
.style("stroke","black")
.attr("r", function(d,i) {
return rmax / ((-1)*((i+1) - 5));
}
)
;
legsymbols.append("text")
.attr("x", function(d,i) {return 5+2*rmax / ((-1)*((i+1) - 5)) ;})
.attr("y", legendspace + 2*rmax)
.style("text-anchor", "start")
.text(function(d) { return d; });
legend
.append("text")
.text("Wisconsin Employment:")
.attr("y", rmax*2+ legendspace)
;
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment