A random sample of 100 infant deaths from 2009 colored by infant’s sex.
This is a work in progress.
See 2009 Cohort Linked Birth/Infant Death Data Set Guide (pdf).
Source: National Bureau of Economic Research
forked from syntagmatic‘s block: Infant Deaths
<!DOCTYPE html>
<meta charset="utf-8">
<title>Infant Death</title>
<style>
svg {
font: 10px sans-serif;
}
.foreground path {
fill: none;
stroke: #222;
stroke-opacity: 0.38;
pointer-events: none;
stroke-width: 1.5px;
}
.axis .title {
font-size: 8px;
font-weight: bold;
text-transform: uppercase;
transform: rotate(-12deg) translate(-5px,-6px);
}
.axis line,
.axis path {
fill: none;
stroke: #000;
stroke-width: 1px;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
stroke-width: 1px;
}
pre {
width: 900px;
margin: 10px 30px;
tab-size: 12;
font-size: 12px;
overflow: auto;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var margin = {top: 50, right: 80, bottom: 20, left: 80},
width = 960 - margin.left - margin.right,
height = 220 - margin.top - margin.bottom;
var types = {
"Number": {
key: "Number",
coerce: function(d) { return +d; },
extent: d3.extent,
within: function(d, extent) { return extent[0] <= d && d <= extent[1]; },
defaultScale: d3.scale.linear().range([height, 0])
},
"String": {
key: "String",
coerce: String,
extent: function (data) { return data.sort(); },
within: function(d, extent, dim) { return extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1]; },
defaultScale: d3.scale.ordinal().rangePoints([0, height])
}
};
var dimensions = [
{
key: "mager14",
description: "Mother's Age",
scale: d3.scale.ordinal().rangePoints([0, height]),
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Under 15",
3: "15",
4: "16",
5: "17",
6: "18",
7: "19",
8: "20-24",
9: "25-29",
10: "30-34",
11: "35-39",
12: "40-44",
13: "45-49",
14: "50-54"
}[d]
}),
domain: [1,3,4,5,6,7,8,9,10,11,12,13,14]
},
{
key: "fagerec11",
description: "Father's Age",
type: types["String"],
domain: [1,2,3,4,5,6,7,8,9,10,11],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Under 15",
2: "15-19",
3: "20-24",
4: "25-29",
5: "30-34",
6: "35-39",
7: "40-44",
8: "45-49",
9: "50-54",
10: "55-98",
11: "Not stated"
}[d]
})
},
{
key: "sex",
description: "Sex",
type: types["String"]
},
{
key: "dob_yy",
description: "Birth Year",
type: types["String"]
},
{
key: "dob_mm",
description: "Birth Month",
type: types["String"],
domain: d3.range(1,13),
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Jan",
2: "Feb",
3: "Mar",
4: "Apr",
5: "May",
6: "Jun",
7: "Jul",
8: "Aug",
9: "Sep",
10: "Oct",
11: "Nov",
12: "Dec"
}[d]
})
},
{
key: "mar",
description: "Mother's Marital Status",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Yes",
2: "No",
9: "Unknown"
}[d]
})
},
{
key: "meduc_rec",
description: "Mother's Education",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "0-8 years",
2: "9-11 years",
3: "12 years",
4: "13-15 years",
5: "16+ years",
6: "Not stated"
}[d]
})
},
{
key: "mpcb",
description: "Month Prenatal Care Began",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
if (d == 0) return "No care";
if (d <= 10) return d + " months";
if (d == 99) return "Unknown";
})
},
{
key: "wtgain_rec",
description: "Weight Gain",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
if (d < 98) return d + " lbs";
if (d = 98) return "98+ lbs";
if (d = 99) return "Unknown";
return "null"
})
},
{
key: "cig_rec6",
description: "Cigarettes Per Day",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
0: "Non-smoker",
1: "1-5",
2: "6-10",
3: "11-20",
4: "21-40",
5: "41+",
6: "Unknown"
}[d]
})
},
{
key: "uop_induc",
description: "Induction of Labor",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Yes",
2: "No",
9: "Unknown"
}[d]
})
},
{
key: "ume_vag",
description: "Vaginal Delivery",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Yes",
2: "No",
9: "Unknown"
}[d]
})
},
{
key: "gestrec10",
description: "Gestation (weeks)",
type: types["String"],
axis: d3.svg.axis().orient("left")
.tickFormat(function(d) {
return {
1: "Under 20",
2: "20-27",
3: "28-31",
4: "32-33",
5: "34-36",
6: "37-38",
7: "39",
8: "40",
9: "41",
10: "42+",
99: "Unknown"
}[d]
})
},
];
var colordimension = dimensions.filter(function(d) { return d.key == "sex"; })[0];
var color = d3.scale.ordinal()
.range(["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"]);
var x = d3.scale.ordinal()
.domain(dimensions.map(function(dim) { return dim.key; }))
.rangePoints([0, width]);
var line = d3.svg.line()
.defined(function(d) { return !isNaN(d[1]); });
var yAxis = d3.svg.axis()
.orient("left");
var svg = d3.select("body").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 output = d3.select("body").append("pre");
var foreground = svg.append("g")
.attr("class", "foreground");
var axes = svg.selectAll(".axis")
.data(dimensions)
.enter().append("g")
.attr("class", "axis")
.attr("transform", function(d) { return "translate(" + x(d.key) + ")"; });
d3.csv("linkco2009us_num.csv", function(error, rawdata) {
if (error) throw error;
// take subset of data
data = d3.shuffle(rawdata).slice(0,100);
data.forEach(function(d) {
dimensions.forEach(function(p) {
d[p.key] = p.type.coerce(d[p.key]);
});
});
// type/dimension default setting happens here
dimensions.forEach(function(dim) {
if (!("domain" in dim)) {
// detect domain using dimension type's extent function
dim.domain = d3.functor(dim.type.extent)(data.map(function(d) { return d[dim.key]; }));
// TODO - this line only works because the data encodes data with integers
// Sorting/comparing should be defined at the type/dimension level
dim.domain.sort(function(a,b) {
return a - b;
});
}
if (!("scale" in dim)) {
// use type's default scale for dimension
dim.scale = dim.type.defaultScale.copy();
}
dim.scale.domain(dim.domain);
});
color.domain(colordimension.scale.domain());
foreground.selectAll("path")
.data(data)
.enter().append("path")
.attr("d", draw)
.style("stroke", function(d) { return color(d[colordimension.key]); });
axes.append("g")
.attr("class", "axis")
.each(function(d) {
var renderAxis = "axis" in d
? d.axis.scale(d.scale) // custom axis
: yAxis.scale(d.scale); // default axis
d3.select(this).call(renderAxis);
})
.append("text")
.attr("class", "title")
.attr("text-anchor", "start")
.text(function(d) { return "description" in d ? d.description : d.key; });
// Add and store a brush for each axis.
axes.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(d.brush = d3.svg.brush()
.y(d.scale)
.on("brushstart", brushstart)
.on("brush", brush));
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
output.text(d3.tsv.format(data));
function draw(d) {
return line(dimensions.map(function(dim) {
return [x(dim.key), dim.scale(d[dim.key])];
}));
}
function brushstart() {
d3.event.sourceEvent.stopPropagation();
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) { return !p.brush.empty(); }),
extents = actives.map(function(p) { return p.brush.extent(); });
var selected = [];
d3.selectAll(".foreground path").style("display", function(d) {
if (actives.every(function(dim, i) {
// test if point is within extents for each active brush
return dim.type.within(d[dim.key], extents[i], dim);
})) {
selected.push(d);
return null;
}
return "none";
});
output.text(d3.tsv.format(selected));
}
});
</script>