Skip to content

Instantly share code, notes, and snippets.

@dongyi
Created November 25, 2017 01:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dongyi/34603c23527e93361ded9105d5134890 to your computer and use it in GitHub Desktop.
Save dongyi/34603c23527e93361ded9105d5134890 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<!-- Charset and load required libraries -->
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.0.0.min.js"></script>
<style>
/* Title */
h2 {
text-align: center;
}
/* Normal text */
div {
text-align: justify;
}
/* Warning about browsers */
p {
text-align: center;
font-style: italic;
}
</style>
<script type="text/javascript">
"use strict"; // We must declare all variables
var margin = 50,
width = 700 - margin,
height = 450 - margin;
/* One of the plots calculates the average number of home runs (HR) per
group of height in order to represent it as circles whose surface depends
on the value. We passed to dimple the sqrt of the values to make the
surfaces comparables. So to recover the original value of the average
withouth using sqrt, we use this function, which is needed to correctly
represent the real value in the tooltips.
*/
function avgHRByHeight(myData, value) {
var filteredData = myData.filter(function(d) {
return d['height'] == value;
});
if (filteredData.length > 0) {
var sum = 0.0;
for (var i = 0; i < filteredData.length; i++) {
sum = sum + +filteredData[i]['HR'];
}
return sum/filteredData.length;
} else {
return 0;
}
}
/* This function creates the structure of the page, with the title, a
summary and two plots */
function draw(data) {
d3.select("body")
.append("h2")
.text("Baseball Performance");
d3.select("body")
.append("div")
.text("Here we present a visual analysis about some parameters "
+ "that affects the performance of the baseball players. The "
+ "dataset, provided by Udacity, contains 1,157 baseball "
+ "players including their handedness (right or left handed), "
+ "height (in inches), weight (in pounds), batting average, "
+ "and home runs. So performance is measured as their batting "
+ "average and the number of home runs; parameters are "
+ "handedness, height and weight. Since height and weight are "
+ "positively correlated (data not shown), we will use only "
+ "height parameter. Our conclusions are: 1) smaller players "
+ "are better batting; 2) medium players are more constant in "
+ "their home run rates; and 3) left-handed players are "
+ "better batting and doing home runs. Please note that the "
+ "values at the ends (small and large players) may be "
+ "slightly biased because they are under-represented (i.e: "
+ "only 4 players with height 67, the big bubble on the left "
+ "chart).");
d3.select("body")
.append("p")
.text("Please use Chrome or Safari browsers for a correct "
+ "visualization.");
line_bubble_plot(data);
bar_line_plot(data);
};
/* Plots a graph of bating average and home runs averaged by groups of
height */
function line_bubble_plot(data) {
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin)
.attr("height", height + margin)
.append('g')
.attr('class','chart');
var myChart = new dimple.chart(svg, data);
// Add centered title
svg.append("text")
.attr("x", myChart._xPixels() + myChart._widthPixels() / 2)
.attr("y", myChart._yPixels() - 20)
.style("text-anchor", "middle")
.style("font-family", "sans-serif")
.style("font-weight", "bold")
.style("font-size", "14")
.text("Shorter players have high batting averages, mid-height are "
+ " more constant in their HR rates");
// Create main x and y axis and assign titles and numeric format
var x = myChart.addCategoryAxis("x", "height");
x.title = "Player's height (inches)";
var y = myChart.addMeasureAxis("y", "avg");
y.title = "Average of player's batting performnace (avg)";
y.tickFormat = ',.2f'; // Two decimal places
// Create a "third" dimension to include a third parameter (HR - home
// runs) represented by the size of the spot (bubble). Since we want
// the area of the circle to be proportional to the value of HR, we
// use instead the sqrt of HR (HRsqrt)
myChart.addMeasureAxis("z", "HRsqrt");
// Add series: line for the main (batting average per height) and
// bubbles for the secondary (size of the bubble proportional to
// the average number of HR for the height group). Then change one
// of the colors for a better contrast
var serie1 = myChart.addSeries("Home runs (HR)", dimple.plot.bubble);
serie1.aggregate = dimple.aggregateMethod.avg;
myChart.addSeries("Batting average (avg)", dimple.plot.line)
.aggregate = dimple.aggregateMethod.avg;
myChart.assignColor("Batting average (avg)", "red");
// The automatic tooltip shows the averaged sqrt value of HR, show we
// need to create a custom tooltip fixing it using the function
// avgHRByHeight to recover the average value without using sqrt
serie1.getTooltipText = function (e) {
return [
e.aggField[0],
"height:" + e.x,
"avg: " + e.y.toFixed(2),
"HR: " + avgHRByHeight(data, e.x).toFixed(2)
];
};
myChart.addLegend(500, 50, 100, 100, "left");
myChart.draw();
};
/* Plots a bar graph of bating average and home runs averaged by groups of
handedness */
function bar_line_plot(data) {
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin)
.attr("height", height + margin)
.append('g')
.attr('class','chart');
var myChart = new dimple.chart(svg, data);
// Add centered title
svg.append("text")
.attr("x", myChart._xPixels() + myChart._widthPixels() / 2)
.attr("y", myChart._yPixels() - 20)
.style("text-anchor", "middle")
.style("font-family", "sans-serif")
.style("font-weight", "bold")
.style("font-size", "14")
.text("Left-handed players has the best batting averages and "
+ "number of home runs combination");
// Create main x and y axis and assign titles and numeric format.
// There are two different y axis: 1) home runs and 2) average
// batting. In this case data are grouped by handedness (x axis)
var x = myChart.addCategoryAxis("x", "handedness");
x.title = "Player's handedness (R: Right - L: Left - B: Both)";
var y1 = myChart.addMeasureAxis("y", "HR");
y1.title = "Average of player's home runs (HR)";
var y2 = myChart.addMeasureAxis("y", "avg");
y2.title = "Average of player's batting performance (avg)";
y2.tickFormat = ',.2f'; // Two decimal places
// Add series: bar for the left y axis (average number of home runs)
// and line for the right y axis (batting average). We use a line
// for a better distinction between y axis. Also we change one
// of the colors for a better contrast
myChart.addSeries("Home runs (HR)", dimple.plot.bar, [x, y1])
.aggregate = dimple.aggregateMethod.avg;
myChart.addSeries("Batting average (avg)", dimple.plot.line, [x, y2])
.aggregate = dimple.aggregateMethod.avg;
myChart.addSeries("Batting average (avg)", dimple.plot.bubble, [x, y2])
.aggregate = dimple.aggregateMethod.avg;
myChart.assignColor("Batting average (avg)", "red");
myChart.addLegend(500, 94, 100, 100, "left");
myChart.draw();
};
</script>
</head>
<body>
<script type="text/javascript">
// We include an accessor function to create a new variable HRsqrt for
// use it when representing bubbles areas based on HR. Note: When plotting
// bubbles, the radius should be proportional to the square root of the
// variable. Otherwise, doubling the variables value will quadruple the
// circle area.
d3.csv("baseball_data.csv",
function(d) {
d['HRsqrt'] = Math.sqrt(d['HR']);
return d;
},
draw);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment