forked from zanarmstrong's block: comet chart (prototype)
forked from zanarmstrong's block: comet chart - input your own data
forked from zanarmstrong's block: comet chart - input your own data
forked from zanarmstrong's block: comet chart (prototype)
forked from zanarmstrong's block: comet chart - input your own data
forked from zanarmstrong's block: comet chart - input your own data
| body { | |
| font-family: sans-serif; | |
| } | |
| .segments polygon { | |
| shape-rendering: geometricPrecision; | |
| } | |
| .axis path { | |
| stroke: grey; | |
| stroke-width: 1px; | |
| } | |
| .axis line { | |
| fill: none; | |
| stroke: #727272; | |
| shape-rendering: crispEdges; | |
| stroke-width: .2; | |
| } | |
| .axis text { | |
| font-size: 11px; | |
| fill: #727272; | |
| } | |
| .label { | |
| fill: grey; | |
| stroke: none; | |
| font-size: 16px; | |
| } |
| // define variables | |
| var margin = { | |
| top: 0, | |
| right: 20, | |
| bottom: 50, | |
| left: 70 | |
| }, | |
| width = 500, | |
| height = 400; | |
| var formatAsNumber = d3.format(",.0f") | |
| var segmentName = 'birthweight'; | |
| // standard insertion of svg element | |
| var svg = d3.select("#chart") | |
| .append('svg') | |
| .attr('width', width + margin.left + margin.right) | |
| .attr('height', height + margin.top + margin.bottom); | |
| var segments = svg.append("g") | |
| .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') | |
| .attr("class", "segments"); | |
| // add labels | |
| segments.append("text") | |
| .attr("class", "x label") | |
| .attr("x", width / 2) | |
| .attr("y", height + 40) | |
| .style("text-anchor", "middle") | |
| .text(mapping.titleWeight); | |
| segments.append("text") | |
| .attr("transform", "rotate(-90)") | |
| .attr("class", "y label") | |
| .attr("x", -height / 2) | |
| .attr("y", -40) | |
| .style("text-anchor", "middle") | |
| .text(mapping.titleValue); | |
| // call and use data | |
| d3.csv("data.csv", function(error, data) { | |
| if (error) return console.error('error'); | |
| // filter by filter category, if desired | |
| data = data.filter(function(d) { | |
| if (mapping.filterCat != '') { | |
| return d[mapping.filterName] == mappping.filterCat; | |
| } else { | |
| return d; | |
| } | |
| }); | |
| // set scales | |
| scales = applyData(data); | |
| // add the comets | |
| drawComets(segments, data); | |
| // adding x axis, and y axis | |
| addAxis(segments, scales.size, 'bottom'); | |
| addAxis(segments, scales.value, 'left') | |
| }); |
| // graph elements | |
| function addAxis(element, scale, location) { | |
| var axis = d3.svg.axis() | |
| .scale(scale) | |
| .orient(location) | |
| .ticks(15, ",.1s") | |
| .tickSize(3, 0); | |
| element.append("g").attr("class", "axis") | |
| .attr("transform", placeAxis(location)) | |
| .call(axis); | |
| }; | |
| function placeAxis(location) { | |
| if (location == 'bottom') { | |
| return "translate(0," + height + ")"; | |
| } else if (location == 'left') { | |
| return "translate(0,0)"; | |
| } | |
| } | |
| function applyData(data) { | |
| // initialize counter variables | |
| var maxValue = 0, | |
| maxWeight = 0, | |
| minValue = data[0].startvalue, | |
| minWeight = data[0].startweight, | |
| diff = 0, | |
| sizeSum = [0, 0], | |
| comboSum = [0, 0]; | |
| // use data to define max value, weight, weight diffs, and sum size and combo | |
| data.forEach(function(d) { | |
| d.weightDiff = +d.endweight - +d.startweight; | |
| if (Math.abs(d.weightDiff) > diff) { | |
| diff = Math.abs(d.weightDiff) | |
| }; | |
| maxValue = Math.max(maxValue, +d.startvalue, +d.endvalue); | |
| maxWeight = Math.max(maxWeight, +d.startweight, +d.endweight); | |
| minValue = Math.min(minValue, +d.startvalue, +d.endvalue); | |
| minWeight = Math.min(minWeight, +d.startweight, +d.endweight); | |
| // calculate for aggregate | |
| sizeSum = [sizeSum[0] + +d.startweight, | |
| sizeSum[1] + +d.endweight | |
| ]; | |
| comboSum = [comboSum[0] + +d.startweight * +d.startvalue, | |
| comboSum[1] + +d.endweight * +d.endvalue | |
| ]; | |
| }) | |
| // calculate and append aggregate data | |
| // assumes same number of segments for start & end | |
| // assumes no missing values | |
| var aggregate = { | |
| startvalue: comboSum[0] / sizeSum[0], | |
| endvalue: comboSum[1] / sizeSum[1], | |
| startweight: sizeSum[0] / data.length, | |
| endweight: sizeSum[1] / data.length, | |
| }; | |
| aggregate[mapping.segmentName] = 'aggregate'; | |
| data.push(aggregate); | |
| // sets x and y scale to determine size of visible boxes | |
| if (scaleOptions.weightScale == 'log') { | |
| var sizeScale = d3.scale.log().clamp(true) | |
| .domain([minWeight * .8, maxWeight * 2]) | |
| .range([0, width]); | |
| } else { | |
| var sizeScale = d3.scale.linear().clamp(true) | |
| .domain([minWeight * .8, maxWeight * 1.1]) | |
| .range([0, width]); | |
| } | |
| if (scaleOptions.valueScale == 'log') { | |
| var valueScale = d3.scale.log().clamp(true) | |
| .domain([minValue * .9, maxValue * 2]) | |
| .range([height, 0]); | |
| } else { | |
| var valueScale = d3.scale.linear().clamp(true) | |
| .domain([minValue * .9, maxValue * 1.1]) | |
| .range([height, 0]); | |
| } | |
| // color scale, based on data diffs | |
| var colorScale = d3.scale.linear() | |
| .domain([-diff, 0, diff]) | |
| .range(['orange', 'grey', 'blue']) | |
| return { | |
| size: sizeScale, | |
| value: valueScale, | |
| color: colorScale | |
| } | |
| }; | |
| // data to polygons | |
| function valuesToPoints(startweight, endweight, startvalue, endvalue, halfWidth) { | |
| points = [ | |
| [startweight, startvalue] | |
| ]; | |
| var a = startweight - endweight; | |
| var b = startvalue - endvalue; | |
| var dist = Math.sqrt(a * a + b * b); | |
| var newPoint1 = [halfWidth / dist * b + endweight, -halfWidth / dist * a + endvalue]; | |
| var newPoint2 = [-halfWidth / dist * b + endweight, halfWidth / dist * a + endvalue]; | |
| points.push(newPoint1, newPoint2); | |
| return points.join(" ") | |
| }; | |
| // function to draw comets | |
| function drawComets(element, data) { | |
| element.selectAll("polygon") | |
| .data(data) | |
| .enter() | |
| .append("polygon") | |
| .attr("points", function(d) { | |
| return valuesToPoints(scales.size(+d.startweight), | |
| scales.size(+d.endweight), | |
| scales.value(+d.startvalue), | |
| scales.value(+d.endvalue), | |
| 3); | |
| }) | |
| .attr("fill", function(d) { | |
| if (d[mapping.segmentName] == 'aggregate') { | |
| // | |
| return 'black'; | |
| } else { | |
| return scales.color(d.weightDiff) | |
| }; | |
| }) | |
| .append("title") | |
| .text(function(d) { | |
| return d[mapping.filterName] + | |
| ', ' + mapping.segmentName + | |
| d[mapping.segmentName] + | |
| ', value: ' + | |
| d.startvalue + ', ' + | |
| d.endvalue + | |
| ' weights ' + | |
| d.startweight + ' ' + | |
| d.endweight; | |
| }); | |
| }; |
| state | birthweight | startvalue | endvalue | startweight | endweight | |
|---|---|---|---|---|---|---|
| Ohio | 2500 - 2999 grams | 5.53 | 4.88 | 101227 | 109151 | |
| Ohio | 1500 - 1999 grams | 29.19 | 26.96 | 9078 | 9904 | |
| Ohio | 1000 - 1499 grams | 67.39 | 59.15 | 4526 | 5038 | |
| Ohio | 4000+ grams | 1.96 | 1.24 | 65199 | 46140 | |
| Ohio | 500 - 999 grams | 336.39 | 287.95 | 3377 | 3445 | |
| Ohio | 2000 - 2499 grams | 13.69 | 11.62 | 28782 | 30884 | |
| Ohio | 3000 - 3499 grams | 3.02 | 2.45 | 219696 | 222982 | |
| Ohio | 499 grams or less | 921.9 | 901.15 | 1114 | 1305 | |
| Ohio | 3500 - 3999 grams | 2.09 | 1.61 | 177442 | 154742 | |
| Georgia | 2500 - 2999 grams | 5.39 | 4.11 | 84094 | 117194 | |
| Georgia | 1500 - 1999 grams | 31.75 | 25.06 | 7748 | 10377 | |
| Georgia | 1000 - 1499 grams | 66.49 | 59.75 | 3880 | 5021 | |
| Georgia | 4000+ grams | 2.03 | 1.67 | 42755 | 35975 | |
| Georgia | 500 - 999 grams | 349.31 | 293.52 | 3338 | 4228 | |
| Georgia | 2000 - 2499 grams | 14.22 | 10.39 | 24539 | 34175 | |
| Georgia | 3000 - 3499 grams | 2.66 | 2.14 | 172853 | 227039 | |
| Georgia | 499 grams or less | 904.81 | 728.06 | 956 | 1151 | |
| Georgia | 3500 - 3999 grams | 2.15 | 1.63 | 126734 | 137645 | |
| New Jersey | 2500 - 2999 grams | 3.93 | 2.36 | 74847 | 82086 | |
| New Jersey | 1500 - 1999 grams | 20.08 | 16.37 | 7120 | 7513 | |
| New Jersey | 1000 - 1499 grams | 56.28 | 35.94 | 3536 | 3645 | |
| New Jersey | 4000+ grams | 1.22 | 1.09 | 48311 | 33939 | |
| New Jersey | 500 - 999 grams | 297.12 | 269.42 | 2955 | 2639 | |
| New Jersey | 2000 - 2499 grams | 9.97 | 6.84 | 21156 | 22957 | |
| New Jersey | 3000 - 3499 grams | 1.95 | 1.5 | 165760 | 173854 | |
| New Jersey | 499 grams or less | 875.33 | 870.97 | 762 | 651 | |
| New Jersey | 3500 - 3999 grams | 1.23 | 0.99 | 132117 | 118722 | |
| Florida | 2500 - 2999 grams | 4.55 | 3.87 | 132288 | 177337 | |
| Florida | 1500 - 1999 grams | 29.05 | 25.01 | 11601 | 15155 | |
| Florida | 1000 - 1499 grams | 56.2 | 53.75 | 5783 | 7275 | |
| Florida | 4000+ grams | 1.81 | 1.59 | 70266 | 58431 | |
| Florida | 500 - 999 grams | 319.63 | 290.92 | 4696 | 5871 | |
| Florida | 2000 - 2499 grams | 12.55 | 10.32 | 37381 | 49210 | |
| Florida | 3000 - 3499 grams | 2.52 | 1.92 | 288298 | 364768 | |
| Florida | 499 grams or less | 911.6 | 911.06 | 1233 | 1664 | |
| Florida | 3500 - 3999 grams | 1.63 | 1.32 | 214462 | 226844 | |
| Michigan | 2500 - 2999 grams | 5.87 | 3.93 | 84729 | 83716 | |
| Michigan | 1500 - 1999 grams | 28.38 | 31.25 | 8281 | 7776 | |
| Michigan | 1000 - 1499 grams | 71.52 | 55.03 | 3929 | 3816 | |
| Michigan | 4000+ grams | 2.04 | 1.67 | 59301 | 41855 | |
| Michigan | 500 - 999 grams | 347.11 | 295.4 | 3218 | 3084 | |
| Michigan | 2000 - 2499 grams | 13.07 | 9.61 | 25024 | 24753 | |
| Michigan | 3000 - 3499 grams | 2.63 | 2.22 | 190941 | 179909 | |
| Michigan | 499 grams or less | 891.05 | 870.88 | 1028 | 1092 | |
| Michigan | 3500 - 3999 grams | 1.91 | 1.62 | 158394 | 132157 | |
| Texas | 3000 - 3499 grams | 2.54 | 2.06 | 514828 | 653989 | |
| Texas | 1000 - 1499 grams | 61.69 | 53.48 | 8753 | 12079 | |
| Texas | 2500 - 2999 grams | 4.55 | 3.83 | 226968 | 320675 | |
| Texas | 1500 - 1999 grams | 30.92 | 28.16 | 18695 | 26033 | |
| Texas | 4500+ grams | 2.23 | 2.37 | 17513 | 12673 | |
| Texas | 4000 - 4499 grams | 1.68 | 1.67 | 99225 | 86139 | |
| Texas | 499 grams or less | 703.34 | 708.93 | 1409 | 2642 | |
| Texas | 3500 - 3999 grams | 1.87 | 1.4 | 373838 | 392317 | |
| Texas | 500 - 999 grams | 308.81 | 265.38 | 7163 | 8859 | |
| Texas | 2000 - 2499 grams | 13.27 | 10.76 | 60726 | 85758 | |
| New York | 2500 - 2999 grams | 4.3 | 2.78 | 176330 | 184645 | |
| New York | 1500 - 1999 grams | 25.99 | 20.74 | 16082 | 16300 | |
| New York | 1000 - 1499 grams | 56.79 | 46.98 | 7906 | 7918 | |
| New York | 4000+ grams | 1.57 | 1.07 | 106329 | 77806 | |
| New York | 500 - 999 grams | 338.98 | 273.29 | 6552 | 5840 | |
| New York | 2000 - 2499 grams | 10.92 | 7.88 | 49348 | 50356 | |
| New York | 3000 - 3499 grams | 2.07 | 1.45 | 389495 | 388484 | |
| New York | 499 grams or less | 931.61 | 927.12 | 1506 | 1276 | |
| New York | 3500 - 3999 grams | 1.43 | 1.12 | 296709 | 263005 | |
| Illinois | 2500 - 2999 grams | 5.75 | 3.78 | 121146 | 125074 | |
| Illinois | 1500 - 1999 grams | 31.83 | 24.81 | 11436 | 11487 | |
| Illinois | 1000 - 1499 grams | 70.31 | 51.46 | 5504 | 5344 | |
| Illinois | 4000+ grams | 1.77 | 1.37 | 74666 | 54564 | |
| Illinois | 500 - 999 grams | 364.81 | 300.19 | 4490 | 4204 | |
| Illinois | 2000 - 2499 grams | 14.06 | 10.09 | 35357 | 35871 | |
| Illinois | 3000 - 3499 grams | 3.11 | 1.96 | 268166 | 268672 | |
| Illinois | 499 grams or less | 901.83 | 878.87 | 1477 | 1453 | |
| Illinois | 3500 - 3999 grams | 2.04 | 1.36 | 210021 | 187259 | |
| Pennsylvania | 2500 - 2999 grams | 4.8 | 4.51 | 94587 | 104298 | |
| Pennsylvania | 1500 - 1999 grams | 30.89 | 23.89 | 8644 | 9711 | |
| Pennsylvania | 1000 - 1499 grams | 63.76 | 51.12 | 4203 | 4851 | |
| Pennsylvania | 4000+ grams | 1.82 | 1.64 | 64457 | 50705 | |
| Pennsylvania | 500 - 999 grams | 326.86 | 285.59 | 3298 | 3456 | |
| Pennsylvania | 2000 - 2499 grams | 12.32 | 10.13 | 27202 | 30112 | |
| Pennsylvania | 3000 - 3499 grams | 2.51 | 2.19 | 212567 | 222310 | |
| Pennsylvania | 499 grams or less | 920.35 | 918.74 | 1130 | 1366 | |
| Pennsylvania | 3500 - 3999 grams | 1.69 | 1.38 | 174075 | 162801 | |
| California | 3000 - 3499 grams | 2.33 | 1.57 | 802668 | 855510 | |
| California | 1000 - 1499 grams | 68.98 | 54.7 | 12351 | 13237 | |
| California | 2500 - 2999 grams | 4.6 | 3.13 | 331059 | 377355 | |
| California | 1500 - 1999 grams | 32.57 | 24.98 | 25636 | 28865 | |
| California | 4500+ grams | 2.37 | 2.12 | 36300 | 24560 | |
| California | 4000 - 4499 grams | 1.67 | 1.12 | 194276 | 153362 | |
| California | 499 grams or less | 879.21 | 850.28 | 2318 | 2518 | |
| California | 3500 - 3999 grams | 1.7 | 1.21 | 642323 | 597310 | |
| California | 500 - 999 grams | 338.35 | 295.25 | 8967 | 9338 | |
| California | 2000 - 2499 grams | 12.98 | 9.85 | 81989 | 93270 |
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <title>Comet Chart</title> | |
| <link rel="stylesheet" href="cometChart.css"> | |
| <header> | |
| </header> | |
| <p>To use this chart with your own data:</p> | |
| <p>(1) paste your data into the data.csv</p> | |
| <p>(2) change the column names in the mappingNames.js file</p> | |
| <p>(optional) set the scale for each axis to log or linear</p> | |
| <div id="chart"></div> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <script src="mappingNames.js"></script> | |
| <script src="cometChartFunctions.js"></script> | |
| <script src="cometChart.js"></script> |
| var mapping = { | |
| // columns names for "value" metrics (y-axis), and a title for the size/weight value to use on the y-axis | |
| startValue: "deathRate_before", | |
| endValue: "deathRate_after", | |
| titleValue: "Fetal Death Rate", | |
| // column names for "weight" metrics (x-axis), and a title for the size/weight variable to use on the x-axis | |
| startWeight: "numBabiesBorn_before", | |
| endWeight: "numBabiesBorn_after", | |
| titleWeight: "Number of Babies Born", | |
| // column to segment the data into subgroups | |
| segmentName: "birthweight", | |
| // if you want to filter by another variable, type the name of that column here - and the category you want to filter as 'filterCat', as shown in the options that are commented out | |
| filterName: "state", | |
| filterCat: "Ohio", | |
| //filterName: "state", | |
| //filterCat: "Ohio" | |
| } | |
| var scaleOptions = { | |
| // set scale (either 'linear' or 'log') | |
| weightScale: "log", | |
| valueScale: "log" | |
| } |