D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
jwilber
Full window
Github gist
basic joy plot
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <style> /* .y-axis text, .x-axis text { fill: white; opacity: .85; } .y-axis line, .y-axis path { opacity: 0} .x-axis line, .x-axis path { stroke: white; opacity: .85; } */ .y-axis, .x-axis { font-family: 'arial' } </style> </head> <!-- Load d3.js --> <script src="https://d3js.org/d3.v4.js"></script> <!-- Create a div where the graph will take place --> <body></body> <!-- <script src="joyplot.js"></script> --> <script> // set the dimensions and margins of the graph var margin = {top: 120, right: 30, bottom: 20, left:110}, width = 460 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; // append the svg object to the body of the page var svg = d3.select("body") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .style('background-color', 'white') .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //read data d3.csv("https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv", function(data) { // Get the different categories and count them var categories = data.columns.filter(d => !isNaN(data[0][d])) var n = categories.length const {min, max} = csvExtent(data) // Add X axis var x = d3.scaleLinear() .domain([min - 15, max + 15]) .range([ 0, width ]); svg.append("g") .attr('class', 'x-axis') .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)); // Create a Y scale for densities var y = d3.scaleLinear() .domain([0, .25]) .range([ height, 0]); // Create the Y axis for names var yName = d3.scaleBand() .domain(categories) .range([0, height]) .paddingInner(1) svg.append("g") .attr('class', 'y-axis') .call(d3.axisLeft(yName)); // Compute kernel density estimation for each column: var kde = kernelDensityEstimator(kernelEpanechnikov(7), x.ticks(40)) // increase this 40 for more accurate density. var allDensity = [] for (i = 0; i < n; i++) { key = categories[i] density = kde( data.map(function(d){ return d[key]; }) ) allDensity.push({key: key, density: density}) } // Add areas svg.selectAll("areas") .data(allDensity) .enter() .append("path") .attr("transform", function(d){return("translate(0," + (yName(d.key)-height) +")" )}) .datum(d => d.density) .attr("fill", "skyblue") .attr('opacity', 1) .attr("stroke", "azure") .attr("stroke-width", 1) .attr("d", d3.line() .curve(d3.curveStep) .x(function(d) { return x(d[0]); }) .y(function(d) { return y(d[1]); }) ) }) // end csv load // This is what I need to compute kernel density estimation 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; }; } function csvExtent(data) { const colNames = data.columns const extents = colNames.map(col => d3.extent(data, d => +d[col])); const csvMin = d3.min(extents, d => d[0]) const csvMax = d3.max(extents, d => d[1]) return {'min': csvMin, 'max': csvMax} } </script>
https://d3js.org/d3.v4.js