Skip to content

Instantly share code, notes, and snippets.

@dmesquita
Last active August 10, 2017 19:46
Show Gist options
  • Save dmesquita/e417de34d8f6ba24fbe4977b1af85eda to your computer and use it in GitHub Desktop.
Save dmesquita/e417de34d8f6ba24fbe4977b1af85eda to your computer and use it in GitHub Desktop.
Bubble chart with labels
AirLineAbbr Airline Reason Number
9E Pinnacle Airlines Carrier 1270
AA American Airlines Carrier 814
AQ Aloha Airlines Inc. Carrier 25
AS Alaska Airlines Carrier 239
B6 JetBlue Airways Carrier 211
CO Continental Air Lines Carrier 31
DL Delta Air Lines Carrier 401
EV Estafeta Carga Aereas Carrier 333
F9 Frontier Airlines Carrier 6
FL AirTran Airways Carrier 124
HA Hawaiian Airlines Carrier 47
MQ American Eagle Airlines Carrier 929
NW Northwest Airlines Carrier 208
OH Comair Carrier 307
OO Skywest Airlines Carrier 800
UA United Air Lines Carrier 1416
US US Airways Carrier 683
WN Southwest Airlines Carrier 1386
XE Expressjet Airlines Carrier 150
YV Mesa Airlines Carrier 2139
9E Pinnacle Airlines Weather 688
AA American Airlines Weather 342
AQ Aloha Airlines Inc. Weather 0
AS Alaska Airlines Weather 96
B6 JetBlue Airways Weather 0
CO Continental Air Lines Weather 158
DL Delta Air Lines Weather 1006
EV Estafeta Carga Aereas Weather 1341
F9 Frontier Airlines Weather 49
FL AirTran Airways Weather 357
HA Hawaiian Airlines Weather 0
MQ American Eagle Airlines Weather 2528
NW Northwest Airlines Weather 363
OH Comair Weather 1258
OO Skywest Airlines Weather 1646
UA United Air Lines Weather 1107
US US Airways Weather 366
WN Southwest Airlines Weather 1349
XE Expressjet Airlines Weather 1169
YV Mesa Airlines Weather 774
9E Pinnacle Airlines National Air System 163
AA American Airlines National Air System 501
AQ Aloha Airlines Inc. National Air System 0
AS Alaska Airlines National Air System 20
B6 JetBlue Airways National Air System 0
CO Continental Air Lines National Air System 4
DL Delta Air Lines National Air System 127
EV Estafeta Carga Aereas National Air System 63
F9 Frontier Airlines National Air System 0
FL AirTran Airways National Air System 52
HA Hawaiian Airlines National Air System 0
MQ American Eagle Airlines National Air System 2015
NW Northwest Airlines National Air System 259
OH Comair National Air System 7
OO Skywest Airlines National Air System 2238
UA United Air Lines National Air System 477
US US Airways National Air System 336
WN Southwest Airlines National Air System 200
XE Expressjet Airlines National Air System 669
YV Mesa Airlines National Air System 714
EV Estafeta Carga Aereas Security 2
function bubbleChart() {
var width = 940,
height = 940,
maxRadius = 30,
columnForColors = "Reason",
columnForRadius = "Number";
function chart(selection) {
var data = selection.enter().data();
var div = selection,
svg = div.selectAll('svg');
svg.attr('width', width).attr('height', height);
var tooltip = selection
.append("div")
.style("position", "absolute")
.style("visibility", "hidden")
.style("color", "#424242")
.style("padding", "8px")
.style("background-color", "#BDBDBD")
.style("border-radius", "16px")
.style("text-align", "center")
.style("font-family", "monospace")
.style("width", "300px")
.text("");
var simulation = d3.forceSimulation(data)
.force("charge", d3.forceManyBody().strength([-90]))
.force("x", d3.forceX())
.force("y", d3.forceY())
.on("tick", ticked);
function ticked(e) {
circles.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
labels.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
});
}
// var colorCircles = d3.scaleOrdinal(d3.schemeCategory10);
var colorCircles = d3.scaleOrdinal()
.domain(["Carrier", "Weather", "National Air System", "Security"])
.range(["#009688", "#FFB300", "#1E88E5" ,"#C62828"]);
var scaleRadius = d3.scaleLinear().domain([d3.min(data, function(d) {
return +d[columnForRadius];
}), d3.max(data, function(d) {
return +d[columnForRadius];
})]).range([5, 35])
var nodes = svg.selectAll("circle")
.data(data)
.enter();
var circles =
nodes.append("circle")
.attr('r', function(d) {
return scaleRadius(d[columnForRadius])
})
.style("fill", function(d) {
return colorCircles(d[columnForColors])
})
.attr('transform', 'translate(' + [width / 2, height / 2] + ')')
.on("mouseover", function(d) {
tooltip.html("Airline: " + d.Airline + "<br>" + "Reason for cancelation: " + d[columnForColors] + "<br>" + " Number of cancelations: " + d[columnForRadius] );
return tooltip.style("visibility", "visible");
})
.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY - 10) + "px").style("left", (d3.event.pageX + 10) + "px");
})
.on("mouseout", function() {
return tooltip.style("visibility", "hidden");
});
// add airline names as label:
var labels = nodes.append("text").attr("x", function(d){ return d.x; })
.attr("y", function(d){ return d.y ; })
.attr("text-anchor", "middle")
.text(function(d){ return d.Airline; })
.style("fill","black")
.style("font-family","Helvetica Neue, Helvetica, Arial, san-serif")
.style("font-size", "10px")
.attr('transform', 'translate(' + [width / 2, height / 2] + ')');
}
chart.width = function(value) {
if (!arguments.length) {
return width;
}
width = value;
return chart;
};
chart.height = function(value) {
if (!arguments.length) {
return height;
}
height = value;
return chart;
};
chart.columnForColors = function(value) {
if (!arguments.columnForColors) {
return columnForColors;
}
columnForColors = value;
return chart;
};
chart.columnForRadius = function(value) {
if (!arguments.columnForRadius) {
return columnForRadius;
}
columnForRadius = value;
return chart;
};
return chart;
}
/*
If I want to add elements like title, legend, etc,
should I use the same "var something = svg.selectAll("circle")" over and over?
how I can bind them together?
I see, this is a bit confusing. Let's use your example:
You want to show circles AND labels. They will be in the same 'group' right?
I mean, they both will use the same data.
When I wrote
var node = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
the 'svg.selectAll("circle")' is just a way to get and empty selection we can work on
(because .data() only works with a d3-selection). Writing 'svg.selectAll("another-name")'
would also work here, because this would also return an empty selection.
(writing 'svg.selectAll("circle")' is necessary if we want to erase elements, but let's not
focus on it right now).
So, as we only want an empty selection, I can do this to bind circle and labels:
var NODES = svg.selectAll("circle")
.data(data)
.enter();
//nodes has all the 'empty selections' binded with data. I can then append anything I want now
//labels
var labels = NODES.append("text").attr("x", function(d){ return d.x; })
.attr("y", function(d){ return d.y ; })
.attr("text-anchor", "middle")
.text(function(d){ return d.Airline; })
.style("fill","black")
.style("font-family","Helvetica Neue, Helvetica, Arial, san-serif")
.style("font-size", "10px")
.attr('transform', 'translate(' + [width / 2, height / 2] + ')');
//or circles
var circles =
NODES.append("circle")
.attr('r', function(d) {
return scaleRadius(d[columnForRadius])
})
.style("fill", function(d) {
return colorCircles(d[columnForColors])
})
.attr('transform', 'translate(' + [width / 2, height / 2] + ')')
.on("mouseover", function(d) {
tooltip.html("Airline: " + d.Airline + "<br>" + "Reason for cancelation: " + d[columnForColors] + "<br>" + " Number of cancelations: " + d[columnForRadius] );
return tooltip.style("visibility", "visible");
})
.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY - 10) + "px").style("left", (d3.event.pageX + 10) + "px");
})
.on("mouseout", function() {
return tooltip.style("visibility", "hidden");
});
*/
<!DOCTYPE html>
<div class="chart-example" id="chart"><svg></svg></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script>
<script src="bubble_chart.js"></script>
<script>
d3.tsv('AirlineCancel.tsv', function(error, data) {
if (error) {
console.error('Error getting or parsing the data.');
throw error;
}
var chart = bubbleChart().width(900).height(500);
d3.select('#chart').data(data).call(chart);
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment