d3-beeswarm plugin
This example demonstrates the d3-beeswarm plugin, which arranges one-dimensional scatter plots into closely-packed, non-overlapping points. It uses a dedicated one-pass algorithm rather than d3.force layout to avoid disrupting data ordering or requiring iterative equilibrium. The visualization shows word-stem trends from a CSV dataset, rendered as SVG circles with color encoding by rank, and includes interactive controls for sorting, orientation, radius, and extreme-value handling strategies. The plugin’s `d3.beeswarm()` API distributes points along an axis while freeing the perpendicular coordinate to meet the non-overlapping constraint.
AI-generated descriptionThis <a href='http://bl.ocks.org/Kcnarf/5c989173d0e0c74ab4b62161b33bb0a8'>block</a> uses the d3-beeswarm plugin I made (see the <a href='https://github.com/Kcnarf/d3-beeswarm'>Github project</a>). This plugin produces a beeswarm arrangement, thanks to a dedicated algorithm and without the use a the d3.force layout.
Beeswarm is a one-dimensional scatter plot with closely-packed, non-overlapping points. The beeswarm plot is a useful technique when we wish to see not only the measured values of interest for each data point, but also the distribution of these values
Some beeswarm-like plot implementation uses force layout, but the force layout simulation has some drawbacks:
- it naturally tries to reach its equilibrium by rearranging data points in the 2D space, which can be disruptive to the ordering of the data
- it requires several iterations to reach its equilibrium
This beeswarm plugin uses a dedicated one pass algorithm. By default, the plugin arranges data in an horizontal way. In this case, the final arrangement is contraint in x and free in y. This means that data are arranged along the x-axis, and that the position of each data reflects its precise x value. y position doesn't reflect any data-related value, and only serves the non-overlapping constraint. This plugin can also arrange data in a vertical way.
Even if this block works fine, the plugin is an on-going work. See the Github project's <a href='https://github.com/Kcnarf/d3.layout.beeswarm/issues'>issues</a> for possible enhancements.
Usages
var swarm = d3.beeswarm()
.data(data) // set the data to arrange
.distributeOn(function(d){ // set the value accessor to distribute on
return xScale(d.trend); // evaluated once on each element of data
}) // when starting the arrangement
.radius(4) // set the radius for overlapping detection
.orientation("horizontal") // set the orientation of the arrangement
// could also be 'vertical'
.side("symetric") // set side(s) available for accumulation;
// could also be 'positive' or 'negative'
.arrange(); // launch arrangement computation;
// return an array of {datum: , x: , y: }
// where datum refers to an element of data
// each element of data remains unchanged
Then, later in your code, in order to draw the swarm:
d3.selectAll("circle")
.data(swarm)
.enter()
.append("circle")
.attr("cx", function(bee) { return bee.x; })
.attr("cy", function(bee) { return bee.y; })
.attr("r", 4)
.style("fill", function(bee) { return fill(bee.datum.rank); })
In the last line, bee.datum refers to the original datum.
Acknowledgments to:
- <a href='https://d3js.org/'>D3.js</a> (v3.5.5)
- <a href='http://blockbuilder.org'>blockbuilder.org</a>
- <a href='http://workshop.chromeexperiments.com/'>dat.gui</a>