Built with blockbuilder.org
Last active
November 22, 2019 19:32
-
-
Save avrasgoldman/f2bc5d01c02d12075a3d9bc971d76d27 to your computer and use it in GitHub Desktop.
bean explorer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ID | food_group | beans | Calcium, Ca (mg) | Carbohydrate, by difference (g) | Total lipid (fat) (g) | Fiber, total dietary (g) | Iron, Fe (mg) | Magnesium, Mg (mg) | Protein (g) | Riboflavin (mg) | Sugars, total (g) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | Legumes | black | 27 | 23.71 | 0.54 | 8.7 | 2.1 | 0.444 | 8.86 | 0.059 | 0.32 | |
2 | Legumes | kidney | 28 | 22.8 | 0.5 | 6.4 | 2.94 | 0.477 | 8.67 | 0.058 | 0.32 | |
3 | Legumes | red kidney | 28 | 22.8 | 0.5 | 7.4 | 2.94 | 0.477 | 8.67 | 0.058 | 0.32 | |
4 | Legumes | navy | 69 | 26.05 | 0.62 | 10.5 | 2.36 | 0.527 | 8.23 | 0.066 | 0.37 | |
5 | Legumes | pink | 52 | 27.91 | 0.49 | 5.3 | 2.3 | 0.548 | 9.06 | 0.063 | 0.36 | |
6 | Legumes | pinto | 46 | 26.22 | 0.65 | 9 | 2.09 | 0.453 | 9.01 | 0.062 | 0.34 | |
7 | Legumes | white | 90 | 25.09 | 0.35 | 6.3 | 3.7 | 0.636 | 9.73 | 0.046 | 0.34 | |
8 | Legumes | yeloow | 62 | 25.28 | 1.08 | 10.4 | 2.48 | 0.455 | 9.16 | 0.103 | 0.34 | |
9 | Legumes | fava | 36 | 19.65 | 0.4 | 5.4 | 1.5 | 0.421 | 7.6 | 0.089 | 1.82 | |
10 | Legumes | garbanzo | 49 | 27.42 | 2.59 | 7.6 | 2.89 | 1.03 | 8.86 | 0.063 | 4.8 | |
11 | Legumes | blackeyed | 24 | 20.76 | 0.53 | 6.5 | 2.51 | 0.475 | 7.73 | 0.055 | 3.3 | |
12 | Legumes | lentils | 19 | 19.54 | 0.38 | 7.9 | 3.33 | 0.494 | 9.02 | 0.073 | 1.8 | |
13 | Legumes | lima | 17 | 20.88 | 0.38 | 7 | 2.39 | 0.516 | 7.8 | 0.055 | 2.9 | |
14 | Legumes | mung | 27 | 19.15 | 0.38 | 7.6 | 1.4 | 0.298 | 7.02 | 0.061 | 2 | |
15 | Legumes | peanuts | 55 | 21.26 | 22.01 | 8.8 | 1.01 | 1.023 | 13.5 | 0.063 | 2.47 | |
16 | Legumes | peas | 14 | 20.51 | 0.39 | 8.3 | 1.29 | 0.396 | 8.34 | 0.056 | 2.9 | |
17 | Legumes | soybeans | 102 | 8.36 | 8.97 | 6 | 5.14 | 0.824 | 18.21 | 0.285 | 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<title>Nutrient Parallel Coordinates IV</title> | |
<body> | |
<script src="https://d3js.org/d3.v4.js"></script> | |
<script src="https://bl.ocks.org/syntagmatic/raw/3341641/render-queue.js"></script> | |
<link rel="stylesheet" href="style.css"></link> | |
<script> | |
var margin = {top: 66, right: 110, bottom: 20, left: 188}, | |
width = document.body.clientWidth - margin.left - margin.right, | |
height = 340 - margin.top - margin.bottom, | |
innerHeight = height - 2; | |
var devicePixelRatio = window.devicePixelRatio || 1; | |
var color = d3.scaleOrdinal() | |
.range(["#5DA5B3","#D58323","#DD6CA7","#54AF52","#8C92E8","#E15E5A","#725D82","#776327","#50AB84","#954D56","#AB9C27","#517C3F","#9D5130","#357468","#5E9ACF","#C47DCB","#7D9E33","#DB7F85","#BA89AD","#4C6C86","#B59248","#D8597D","#944F7E","#D67D4B","#8F86C2"]); | |
var types = { | |
"Number": { | |
key: "Number", | |
coerce: function(d) { return +d; }, | |
extent: d3.extent, | |
within: function(d, extent, dim) { return extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1]; }, | |
defaultScale: d3.scaleLinear().range([innerHeight, 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.scalePoint().range([0, innerHeight]) | |
}, | |
"Date": { | |
key: "Date", | |
coerce: function(d) { return new Date(d); }, | |
extent: d3.extent, | |
within: function(d, extent, dim) { return extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1]; }, | |
defaultScale: d3.scaleTime().range([0, innerHeight]) | |
} | |
}; | |
var dimensions = [ | |
{ | |
key: "beans", | |
description: "Beans", | |
type: types["String"], | |
axis: d3.axisLeft() | |
.tickFormat(function(d,i) { | |
return d; | |
}) | |
}, | |
{ | |
key: "Total lipid (fat) (g)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Sugars, total (g)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Calcium, Ca (mg)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Riboflavin (mg)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Iron, Fe (mg)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Magnesium, Mg (mg)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Protein (g)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Fiber, total dietary (g)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
}, | |
{ | |
key: "Carbohydrate, by difference (g)", | |
type: types["Number"], | |
scale: d3.scaleSqrt().range([innerHeight, 0]) | |
} | |
]; | |
var xscale = d3.scalePoint() | |
.domain(d3.range(dimensions.length)) | |
.range([0, width]); | |
var yAxis = d3.axisLeft(); | |
var container = d3.select("body").append("div") | |
.attr("class", "parcoords") | |
.style("width", width + margin.left + margin.right + "px") | |
.style("height", height + margin.top + margin.bottom + "px"); | |
var svg = container.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 canvas = container.append("canvas") | |
.attr("width", width * devicePixelRatio) | |
.attr("height", height * devicePixelRatio) | |
.style("width", width + "px") | |
.style("height", height + "px") | |
.style("margin-top", margin.top + "px") | |
.style("margin-left", margin.left + "px"); | |
var ctx = canvas.node().getContext("2d"); | |
ctx.globalCompositeOperation = 'darken'; | |
ctx.globalAlpha = 0.15; | |
ctx.lineWidth = 1.5; | |
ctx.scale(devicePixelRatio, devicePixelRatio); | |
var output = d3.select("body").append("pre"); | |
var axes = svg.selectAll(".axis") | |
.data(dimensions) | |
.enter().append("g") | |
.attr("class", function(d) { return "axis " + d.key.replace(/ /g, "_"); }) | |
.attr("transform", function(d,i) { return "translate(" + xscale(i) + ")"; }); | |
d3.csv("beans.csv", function(error, data) { | |
if (error) throw error; | |
// shuffle the data! | |
data = d3.shuffle(data); | |
data.forEach(function(d) { | |
dimensions.forEach(function(p) { | |
d[p.key] = !d[p.key] ? null : p.type.coerce(d[p.key]); | |
}); | |
// truncate long text strings to fit in data table | |
for (var key in d) { | |
if (d[key] && d[key].length > 35) d[key] = d[key].slice(0,36); | |
} | |
}); | |
// 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]; })); | |
} | |
if (!("scale" in dim)) { | |
// use type's default scale for dimension | |
dim.scale = dim.type.defaultScale.copy(); | |
} | |
dim.scale.domain(dim.domain); | |
}); | |
var render = renderQueue(draw).rate(50); | |
ctx.clearRect(0,0,width,height); | |
ctx.globalAlpha = d3.min([0.85/Math.pow(data.length,0.3),1]); | |
render(data); | |
axes.append("g") | |
.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.brushY() | |
.extent([[-10,0], [10,height]]) | |
.on("start", brushstart) | |
.on("brush", brush) | |
.on("end", brush) | |
) | |
}) | |
.selectAll("rect") | |
.attr("x", -8) | |
.attr("width", 16); | |
d3.selectAll(".axis.beans .tick text") | |
.style("fill", color); | |
output.text(d3.tsvFormat(data.slice(0,24))); | |
function project(d) { | |
return dimensions.map(function(p,i) { | |
// check if data element has property and contains a value | |
if ( | |
!(p.key in d) || | |
d[p.key] === null | |
) return null; | |
return [xscale(i),p.scale(d[p.key])]; | |
}); | |
}; | |
function draw(d) { | |
ctx.strokeStyle = color(d.beans); | |
ctx.beginPath(); | |
var coords = project(d); | |
coords.forEach(function(p,i) { | |
// this tricky bit avoids rendering null values as 0 | |
if (p === null) { | |
// this bit renders horizontal lines on the previous/next | |
// dimensions, so that sandwiched null values are visible | |
if (i > 0) { | |
var prev = coords[i-1]; | |
if (prev !== null) { | |
ctx.moveTo(prev[0],prev[1]); | |
ctx.lineTo(prev[0]+6,prev[1]); | |
} | |
} | |
if (i < coords.length-1) { | |
var next = coords[i+1]; | |
if (next !== null) { | |
ctx.moveTo(next[0]-6,next[1]); | |
} | |
} | |
return; | |
} | |
if (i == 0) { | |
ctx.moveTo(p[0],p[1]); | |
return; | |
} | |
ctx.lineTo(p[0],p[1]); | |
}); | |
ctx.stroke(); | |
} | |
function brushstart() { | |
d3.event.sourceEvent.stopPropagation(); | |
} | |
// Handles a brush event, toggling the display of foreground lines. | |
function brush() { | |
render.invalidate(); | |
var actives = []; | |
svg.selectAll(".axis .brush") | |
.filter(function(d) { | |
return d3.brushSelection(this); | |
}) | |
.each(function(d) { | |
actives.push({ | |
dimension: d, | |
extent: d3.brushSelection(this) | |
}); | |
}); | |
var selected = data.filter(function(d) { | |
if (actives.every(function(active) { | |
var dim = active.dimension; | |
// test if point is within extents for each active brush | |
return dim.type.within(d[dim.key], active.extent, dim); | |
})) { | |
return true; | |
} | |
}); | |
ctx.clearRect(0,0,width,height); | |
ctx.globalAlpha = d3.min([0.85/Math.pow(selected.length,0.3),1]); | |
render(selected); | |
output.text(d3.tsvFormat(selected.slice(0,24))); | |
} | |
}); | |
function d3_functor(v) { | |
return typeof v === "function" ? v : function() { return v; }; | |
}; | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
min-width: 760px; | |
} | |
.parcoords { | |
display: block; | |
} | |
.parcoords svg, | |
.parcoords canvas { | |
font: 10px sans-serif; | |
position: absolute; | |
} | |
.parcoords canvas { | |
opacity: 0.9; | |
pointer-events: none; | |
} | |
.axis .title { | |
font-size: 10px; | |
transform: rotate(-21deg) translate(-5px,-6px); | |
fill: #222; | |
} | |
.axis line, | |
.axis path { | |
fill: none; | |
stroke: #ccc; | |
stroke-width: 1px; | |
} | |
.axis .tick text { | |
fill: #222; | |
opacity: 0; | |
pointer-events: none; | |
} | |
.axis.manufac_name .tick text, | |
.axis.beans .tick text { | |
opacity: 1; | |
} | |
//.axis:hover line, | |
//.axis:hover path, | |
.axis.active line, | |
.axis.active path { | |
fill: none; | |
stroke: #222; | |
stroke-width: 1px; | |
} | |
.key:hover .beans { | |
font-weight: bold; | |
} | |
.axis:hover .title { | |
font-weight: bold; | |
} | |
.axis:hover .tick text { | |
opacity: 1; | |
} | |
.axis.active .title { | |
font-weight: bold; | |
} | |
.axis.active .tick text { | |
opacity: 1; | |
font-weight: bold; | |
} | |
.brush .extent { | |
fill-opacity: .3; | |
stroke: #fff; | |
stroke-width: 1px; | |
} | |
pre { | |
width: 100%; | |
height: 300px; | |
margin: 6px 12px; | |
tab-size: 40; | |
font-size: 10px; | |
overflow: auto; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment