forked from zanarmstrong‘s block: comet chart (prototype)
forked from zanarmstrong‘s block: comet chart - input your own data
<!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="//d3js.org/d3.v3.min.js"></script>
<script src="mappingNames.js"></script>
<script src="cometChartFunctions.js"></script>
<script src="cometChart.js"></script>
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
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: "",
filterCat: "",
//filterName: "state",
//filterCat: "Ohio"
}
var scaleOptions = {
// set scale (either 'linear' or 'log')
weightScale: "log",
valueScale: "log"
}