Hello, I'm just starting out with JavaScript and trying to implement this code from using my own data.
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
// Read the data and compute summary statistics for each specie
d3.csv("violinsummary.csv", function(data) {
// Show the X scale
var x = d3.scaleBand()
.range([0, width])
.domain(["2017-09", "2017-10","2018-02","2018-03"])
.paddingInner(1)
.paddingOuter(.5);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Show the Y scale
var y = d3.scaleLinear()
.domain([80, 100])
.range([height, 0]);
svg.append("g").call(d3.axisLeft(y));
// Features of density estimate
var kde = kernelDensityEstimator(kernelEpanechnikov(.2), y.ticks(50));
// 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.DATE;})
.rollup(function(d) { // For each key..
input = d.map(function(g) {
return g.Power;});
density = kde(input); // And compute the binning on it.
return(density);
})
.entries(data);
console.log(input);
console.log(density);
// What is the biggest value that the density estimate reach?
var maxNum = 0;
for ( i in sumstat ){
allBins = sumstat[i].value;
kdeValues = allBins.map(function(a){return a[1]});
biggest = d3.max(kdeValues);
if (biggest > maxNum) { maxNum = biggest }
}
console.log(allBins);
console.log(kdeValues);
console.log(biggest);
// The maximum width of a violin must be x.bandwidth = the width dedicated to a group
var xNum = d3.scaleLinear()
.range([0, x.bandwidth()])
.domain([-maxNum,maxNum]);
console.log(sumstat);
// Add the shape to this svg!
svg
.selectAll("myViolin")
.data(sumstat)
.enter() // So now we are working group per group
.append("g")
.attr("transform", function(d){ return("translate(" + x(d.key) +" ,0)") } ) // Translation on the right to be at the group position
.append("path")
.datum(function(d){ return(d.value)}) // So now we are working density per density
.style("stroke", "none")
.style("fill","#69b3a2")
.attr("d", d3.area()
.x0(function(d){ return(xNum(-d[1])) } )
.x1(function(d){ return(xNum(d[1])) } )
.y(function(d){ return(y(d[0])) } )
.curve(d3.curveCatmullRom) // This makes the line smoother to give the violin appearance. Try d3.curveStep to see the difference
)
});
// 2 functions needed for kernel density estimate
function kernelDensityEstimator(kernel, X) {
return function(V) {
return X.map(function(x) {
return [x, d3.mean(V, function(v) { return kernel(x - v); })];
});
};
}
function kernelEpanechnikov(k) {
return function(v) {
return Math.abs(v /= k) <= 1 ? 0.75 * (1 - v * v) / k : 0;
};
}
</script>
I believe there might be an issue in the part of the code where I add the shape to the SVG. All console log outputs seem to display accurate data. I have also compared the data types between the example's data and mine, they remain consistent.
Data (violinsummary.csv):
Power,DATE
89.29,2017-09
89.9,2017-09
91.69,2017-09
89.23,2017-09
91.54,2017-09
88.49,2017-09
89.15,2017-09
90.85,2017-09
89.59,2017-09
93.38,2017-10
92.41,2017-10
90.65,2017-10
91.07,2017-10
90.13,2017-10
91.73,2017-10
91.09,2017-10
93.21,2017-10
91.62,2017-10
89.58,2017-10
90.59,2017-10
92.57,2017-10
89.99,2017-10
90.59,2017-10
88.12,2017-10
91.3,2017-10
89.59,2018-02
91.9,2018-02
87.83,2018-02
90.36,2018-02
91.38,2018-02
91.56,2018-02
91.89,2018-02
90.95,2018-02
90.15,2018-02
90.24,2018-02
94.04,2018-02
85.4,2018-02
88.47,2018-02
92.3,2018-02
92.46,2018-02
92.26,2018-02
88.78,2018-02
90.13,2018-03
89.95,2018-03
92.98,2018-03
91.94,2018-03
90.29,2018-03
91.2,2018-03
94.22,2018-03
90.71,2018-03
93.03,2018-03
91.89,2018-03