A random sample of 750 Abalone measurements from UCI Machine Learning Repository.
Name Data Type Meas. Description
---- --------- ----- -----------
Sex nominal M, F, and I (infant)
Length continuous mm Longest shell measurement
Diameter continuous mm perpendicular to length
Height continuous mm with meat in shell
Whole weight continuous grams whole abalone
Shucked weight continuous grams weight of meat
Viscera weight continuous grams gut weight (after bleeding)
Shell weight continuous grams after being dried
Rings integer +1.5 gives the age in years
xxxxxxxxxx
<meta charset="utf-8">
<title>Abalone</title>
<style>
svg {
font: 10px sans-serif;
}
.foreground path {
fill: none;
stroke: #222;
stroke-opacity: 0.35;
pointer-events: none;
stroke-width: 1.5px;
}
.axis .title {
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
}
.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: 15;
font-size: 12px;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var margin = {top: 30, right: 40, bottom: 20, left: 50},
width = 960 - margin.left - margin.right,
height = 280 - margin.top - margin.bottom;
var types = {
"Number": {
name: "Number",
coerce: function(d) { return +d; },
extent: d3.extent,
within: function(d, extent) { return extent[0] <= d && d <= extent[1]; }
},
"String": {
name: "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]; }
}
};
var dimensions = [
{
name: "Sex",
scale: d3.scale.ordinal().rangePoints([0, height]),
type: types["String"],
domain: ["M", "F", "I"]
},
{
name: "Length",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Diameter",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Height",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Whole weight",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Shucked weight",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Viscera weight",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Shell weight",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
},
{
name: "Rings",
scale: d3.scale.linear().range([height, 0]),
type: types["Number"]
}
];
var color = d3.scale.ordinal()
.range(["#1b9e77","#d95f02","#7570b3"]);
var x = d3.scale.ordinal()
.domain(dimensions.map(function(dim) { return dim.name; }))
.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 dimension = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + x(d.name) + ")"; });
var colordimension = dimensions[0];
d3.csv("abalone.csv", function(error, rawdata) {
if (error) throw error;
// take subset of data
data = d3.shuffle(rawdata).slice(0,750);
data.forEach(function(d) {
dimensions.forEach(function(p) {
d[p.name] = p.type.coerce(d[p.name]);
});
});
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.name]; }));
}
dim.scale.domain(dim.domain);
});
color.domain(colordimension.scale.domain());
svg.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(data)
.enter().append("path")
.attr("d", draw)
.style("stroke", function(d) { return color(d[colordimension.name]); });
dimension.append("g")
.attr("class", "axis")
.each(function(d) { d3.select(this).call(yAxis.scale(d.scale)); })
.append("text")
.attr("class", "title")
.attr("text-anchor", "middle")
.attr("y", -9)
.text(function(d) { return d.name; });
// Add and store a brush for each axis.
dimension.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.name), dim.scale(d[dim.name])];
}));
}
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.name], extents[i], dim);
})) {
selected.push(d);
return null;
}
return "none";
});
output.text(d3.tsv.format(selected));
}
});
</script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js