What
A categorical table whit atributes
Why
Actions are present and comparate, the targets are to identify trends and distribution
how
Order for grades, select, navigate the chanel is hue and saturation and the mark is the line.
decisions:
Display proposed in a bar graph, given that the student is a categorical variable should not be plotted as continuous, and both upline and downlink information is proposed so that it can identify both number of students who have outstanding qualifications and those with lower grades.
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<title>D3: Linked charts</title>
<style type="text/css">
body {
background-color: white;
}
#buttonContainer {
margin-bottom: 10px;
}
button {
padding: 5px;
}
svg {
display: block;
margin-bottom: 10px;
background-color: turquoise;
}
svg text {
font-family: sans-serif;
font-size: 10px;
fill: black;
font-style: bold;
}
g.bar {
fill: #000dcc;
}
g.bar text {
font-family: sans-serif;
font-size: 08px;
fill: black;
font-style: bold;
text-anchor: middle;
opacity: 0;
}
g.bar.highlight text {
opacity: 1;
}
g.bar.highlight rect {
fill: #8ec1ff;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
});
</style>
</head>
<body>
<div id="buttonContainer">
<button id="sort">Sort Descending</button>
<button id="sortDescending">Sort Ascending</button>
</div>
<script type="text/javascript">
//Width, height, padding
var w = 950;
var h = 450;
var padding = 50;
//Sample data
var dataset = [
{"name":23802620, "grades":4.85},
{"name":23802825, "grades":4.865},
{"name":23801894, "grades":3.24},
{"name":23802926, "grades":5},
{"name":23800661, "grades":3.19},
{"name":23800768, "grades":3.98},
{"name":23800972, "grades":4.89},
{"name":23801922, "grades":3.73},
{"name":23805498, "grades":4.795},
{"name":23805913, "grades":4.85},
{"name":23800311, "grades":2.81},
{"name":23806395, "grades":4.72},
{"name":23808850, "grades":3.85},
{"name":23802872, "grades":2.16},
{"name":23802105, "grades":4.715},
{"name":23809880, "grades":4.92},
{"name":23802056, "grades":4.48},
{"name":23807897, "grades":5.2},
{"name":23807916, "grades":5},
{"name":23801962, "grades":3.62},
{"name":23808246, "grades":4.61},
{"name":23802600, "grades":0.11},
{"name":23808311, "grades":4.7}
];
//Configure x and y scale functions
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([ padding, w - padding ], 0.1);
//Now using two different y scales for two different charts
var gradesScale = d3.scale.linear()
.domain([ 0, d3.max(dataset, function(d) {
return d.grades;
}) ])
.rangeRound([ h - padding, padding ]);
var bonusScale = d3.scale.linear()
.domain([ 0, d3.max(dataset, function(d) {
return d.grades;
}) ])
.rangeRound([ h - padding, padding ]);
//Now using two different y axes
var salesAxis = d3.svg.axis()
.scale(gradesScale)
.orient("left")
.ticks(5)
.outerTickSize(0); // remove outer tick mark on axis
var bonusAxis = d3.svg.axis()
.scale(bonusScale)
.orient("left")
.ticks(5)
.outerTickSize(0);
//
// Make the first chart (sales data)
//
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("id", "gradesChart")
.attr("width", w)
.attr("height", h);
//Create groups
var groups = svg.selectAll("g")
.data(dataset)
.enter()
.append("g")
.attr("class", "bar")
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
//Add bar to each group
var rects = groups.append("rect")
.attr("x", 0)
.attr("y", function(d) {
return h - padding;
})
.attr("width", xScale.rangeBand())
.attr("height", 0)
// .attr("fill", "SteelBlue")
;
//Add label to each group
groups.append("text")
.attr("x", xScale.rangeBand() / 2)
.attr("y", function(d) {
return gradesScale(d.grades) - 12;
})
.text(function(d) {
return d.grades;
})
//Add second piece of text - remove css opacity directly
// height is related to height-padding of svg
groups.append("text")
.attr("x", xScale.rangeBand() / 2)
.attr("y", [h - padding/1.6])
.text(function(d) {
return d.name;
})
.style("opacity", 1)
//Transition rects into place
rects.transition()
.delay(function(d, i) {
return i * 100;
})
.duration(1500)
.attr("y", function(d) {
return gradesScale(d.grades);
})
.attr("height", function(d) {
return h - padding - gradesScale(d.grades);
});
//Create y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.attr("opacity", 0)
.call(salesAxis)
.transition()
.delay(2000)
.duration(1500)
.attr("opacity", 1.0);
// Title for chart 1
svg.append("text")
.attr("x", padding/2)
.attr("y", padding/2.5)
.text("Grades")
.style("text-anchor", "start");
//
// Make the second chart (bonus data)
//
//Create SVG element
svg = d3.select("body")
.append("svg")
.attr("id", "bonusChart")
.attr("width", w)
.attr("height", h);
//Create groups
groups = svg.selectAll("g")
.data(dataset)
.enter()
.append("g")
.attr("class", "bar")
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
//Add bar to each group
rects = groups.append("rect")
.attr("x", 0)
.attr("y", function(d) {
return h - padding;
})
.attr("width", xScale.rangeBand())
.attr("height", 0)
// .attr("fill", "SteelBlue")
;
//Add label to each group
groups.append("text")
.attr("x", xScale.rangeBand() / 2)
.attr("y", function(d) {
return bonusScale(d.grades) - 10;
})
.text(function(d) {
return d.grades;
})
//Add second piece of text - remove css opacity directly
// height is related to height-padding of svg
groups.append("text")
.attr("x", xScale.rangeBand() / 2)
.attr("y", [h - padding/1.6])
.text(function(d) {
return d.name;
})
.style("opacity", 1)
//Transition rects into place
rects.transition()
.delay(function(d, i) {
return i * 100;
})
.duration(1500)
.attr("y", function(d) {
return bonusScale(d.grades);
})
.attr("height", function(d) {
return h - padding - bonusScale(d.grades);
});
//Create y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.attr("opacity", 0)
.call(bonusAxis)
.transition()
.delay(2000)
.duration(1500)
.attr("opacity", 1.0);
//New functionality for interaction for ALL groups
//in BOTH charts
d3.selectAll("g.bar")
.on("mouseover", function(d) {
//Instead of d3.select(this), now we want to
//select ALL groups that match the same
//criteria as this one, i.e. this group
//and the corresponding one in the other chart.
//
//We begin by selecting all groups, then
//filtering to exclude those that don't match.
//
//We'll use each person's "name" as a unique
//identifier. (With a real-world data set, you'd
//probably use an ID number here.)
var thisName = d.name;
d3.selectAll("g.bar")
.filter(function(d) {
//If the name from the original group on
//which mouseover was triggered matches the
//name on the group we're evaluating right now…
if (thisName == d.name) {
return true; //…then it's a match
}
})
.classed("highlight", true);
})
.on("mouseout", function() {
//We could be selective, using the same filtering
//criteria above, or, for simplicity, just
//de-highlight all the groups.
d3.selectAll("g.bar")
.classed("highlight", false);
})
// Title for chart 2
svg.append("text")
.attr("x", padding/2)
.attr("y", padding/2.5)
.text("agrupacion")
.style("text-anchor", "start");
//Sort Ascending button - keep both graphs but link.
d3.select("#sort")
.on("click", function() {
//Need to reselect all groups in each chart
d3.selectAll("#gradesChart g.bar").sort(function(a, b) {
return d3.descending(a.grades, b.grades);
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(1000)
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
d3.selectAll("#bonusChart g.bar").sort(function(a, b) {
return d3.descending(a.grades, b.grades);
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(1000)
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
})
;
/// Descending Button - sort both graphs but keep linked
d3.select("#sortDescending")
.on("click", function() {
//Need to reselect all groups in each chart
d3.selectAll("#gradesChart g.bar").sort(function(a, b) {
return d3.ascending(a.grades, b.grades);
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(1000)
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
d3.selectAll("#bonusChart g.bar").sort(function(a, b) { return d3.descending(a.grades, b.grades)
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(1000)
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
});
/// Descending Button - sort both graphs but keep linked
d3.select("#sortRank")
.on("click", function() {
//Need to reselect all groups in each chart
d3.selectAll("#bonusChart g.bar").sort(function(a, b) {
return d3.ascending(a.grades, b.grades);
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(1000)
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
d3.selectAll("#bonusChart g.bar").sort(function(a, b) {
return d3.ascending(a.grades, b.grades);
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(2000)
.attr("transform", function(d, i) {
return "translate(" + xScale(i) + ",0)";
});
});
</script>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js