chart = {
var margin = { top: 10, right: 30, bottom: 30, left: 80 },
jitterWidth = 40,
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
d3.select(container)
.selectAll('svg')
.remove();
var svg = d3
.select(container)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3
.scaleLinear()
.domain([3.5, 8])
.range([height, 0]);
svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
var y = d3
.scaleBand()
.range([0, width])
.domain(["setosa", "versicolor", "virginica"])
.padding(0.05); // This is important: it is the space between 2 groups. 0 means no padding. 1 is the maximum.
svg.append("g").call(d3.axisLeft(y));
// Features of the histogram
var histogram = d3
.histogram()
.domain(x.domain())
.thresholds(x.ticks(20)) // Important: how many bins approx are going to be made? It is the 'resolution' of the violin plot
.value(d => d);
// Compute the binning for each group of the dataset
var sumstat = d3
.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) {
return d.Species;
})
.rollup(function(d) {
var inp = d.map(function(g) {
return g.Sepal_Length;
}); // Keep the variable called Sepal_Length
var bins = histogram(inp); // And compute the binning on it.
return bins;
})
.entries(data);
// What is the biggest number of value in a bin? We need it cause this value will have a width of 100% of the bandwidth.
var maxNum = 0;
for (var i in sumstat) {
var allBins = sumstat[i].value;
var lengths = allBins.map(function(a) {
return a.length;
});
var longuest = d3.max(lengths);
if (longuest > maxNum) {
maxNum = longuest;
}
}
// The maximum width of a violin must be x.bandwidth = the width dedicated to a group
var yNum = d3
.scaleLinear()
.range([0, y.bandwidth()])
.domain([-maxNum, maxNum]);
// Color scale for dots
var myColor = d3
.scaleSequential()
.interpolator(d3.interpolateInferno)
.domain([3, 9]);
// Add individual points with jitter
svg
.selectAll("indPoints")
.data(data)
.enter()
.append("circle")
.attr("cy", function(d) {
return y(d.Species) + y.bandwidth() / 2 - Math.random() * jitterWidth;
})
.attr("cx", function(d) {
return x(d.Sepal_Length);
})
.attr("r", 5)
.style("fill", function(d) {
return myColor(d.Sepal_Length);
})
.attr("stroke", "white");
}