Baseball Pitcher Explorer (open in new tab to see full block)
Brush along one or more dimensions to see a table of Pitchers that match your critera. Output table code from this syntagmatic block.
I scraped the data from Retrosheet with Python's BeautifulSoup. Scraping repo here.
Retrosheet data use statement: 'The information used here was obtained free of charge from and is copyrighted by Retrosheet. Interested parties may contact Retrosheet at "www.retrosheet.org".'
forked from dhoboy's block: Pitcher Explorer
xxxxxxxxxx
<meta charset="utf-8">
<title>Pitchers</title>
<style>
body {
font-family: sans-serif;
}
#main {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
margin: 20px 30px 20px 10px;
}
.title {
margin-left: 9px;
font-size: 14px;
}
.bar, .selection {
fill: steelblue;
}
.axis path,
.axis line {
fill: none;
stroke: #666666;
shape-rendering: crispEdges;
}
.axis text {
fill: #666666;
font-size: 14px;
}
#output {
margin: 0 20px 10px 10px;
}
pre {
width: 100%;
height: 300px;
margin: 6px 12px;
tab-size: 30;
font-size: 10px;
overflow: auto;
}
</style>
<body>
<div id="main"></div>
<div id="output"></div>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 10
};
var height = 100 - margin.top - margin.bottom;
var width = 200 - margin.left - margin.right;
d3.csv("https://dhoboy.github.io/baseball/pitchers.csv", function(data) {
var filteredData = data;
var filters = {};
var columnKey = {
'G': 'Games Pitched',
'GS': 'Games Started',
'CG': 'Complete Games',
'SHO': 'Shutouts',
'GF': 'Relief Games Finished',
'SV': 'Saves',
'IP': 'Innings Pitched',
'H': 'Hits Allowed',
'BFP': 'Batters Faced Pitcher',
'HR': 'Home Runs Allowed',
'R': 'Runs Allowed',
'ER': 'Earned Runs Allowed',
'BB': 'Bases On Balls',
'IB': 'Intentional Bases On Balls',
'SO': 'Strikeouts',
'SH': 'Sacrifice Hits Allowed',
'SF': 'Sacrifice Flies Allowed',
'WP': 'Wild Pitches',
'HBP': 'Hit By Pitch',
'BK': 'Balks',
'GDP': 'Grounded in Double Plays',
'W': 'Wins',
'L': 'Losses',
'ERA': 'Earned Run Average',
'RS': 'Run Support',
'PW': 'Pitcher Wins'
};
var output = d3.select("#output").append("pre")
.text("Brush along at least one dimension above to see a table of results");
var scales = d3.keys(columnKey).reduce(function(prev, next) {
prev[next] = d3.scaleLinear()
.domain(d3.extent(data, function(d) {
return +d[next];
}))
.range([0, width]);
return prev;
}, {});
var reverseScales = d3.keys(columnKey).reduce(function(prev, next) {
prev[next] = d3.scaleLinear()
.domain([margin.left, width + margin.left, height])
.range(d3.extent(data, function(d) {
return +d[next];
}));
return prev;
}, {});
var axes = d3.keys(columnKey).reduce(function(prev, next) {
prev[next] = d3.axisBottom(scales[next]).ticks(3)
return prev;
}, {});
var brushes = d3.keys(columnKey).reduce(function(prev, next) {
prev[next] = d3.brushX().extent([[margin.left, -15], [width + margin.left, height]]);
return prev;
}, {});
var graphs = d3.select("#main").selectAll(".graph")
.data(d3.keys(columnKey))
.enter()
.append("div")
.attr("class", "graph");
graphs.append("div")
.attr("class", "title")
.text(function(d) { return columnKey[d] + ": " + d; });
var svgs = graphs.append("svg")
.attr("id", function(d) { return d; })
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.right + margin.left)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svgs.append("rect")
.attr("class", "bar")
.attr("height", 15)
.attr("width", width)
.attr("rx", 5)
.attr("ry", 5);
d3.keys(columnKey).forEach(function(key) {
var s = d3.select("svg#" + key);
s.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + height + ")")
.call(axes[key]);
s.append("g")
.attr("class", "brush")
.call(brushes[key]);
brushes[key].on("brush end", function() {
var brushSection = d3.brushSelection(this);
if (brushSection === null) {
removeFilter(key);
} else {
var filterInput = [
reverseScales[key](brushSection[0]),
reverseScales[key](brushSection[1])
];
addFilter(key, filterInput);
}
});
});
function addFilter(key, filterInput) {
filters[key] = filterInput;
filterData();
}
function removeFilter(key) {
delete filters[key];
filterData();
}
function filterData() {
// reset filteredData
filteredData = data;
// apply each filter
d3.keys(filters).forEach(function(filterKey) {
filteredData = filteredData.filter(function(d) {
return +d[filterKey] >= filters[filterKey][0] &&
+d[filterKey] <= filters[filterKey][1];
});
});
// only draw result table if you've filtered the dataset somewhat
if (d3.keys(filters).length > 0) {
output.text(d3.tsvFormat(filteredData.slice(0)));
} else {
output.text("Brush along at least one dimension above to see a table of results");
}
}
});
</script>
https://d3js.org/d3.v4.js