├── img ├── end_code.png ├── exercise1.png ├── g_element.png ├── start_code.png ├── create_rect.png ├── numerically.png ├── alphabetically.png ├── create_x_axis.png ├── data_variable.png ├── exercise1_sol.png ├── create_bar_element.png └── team_logo_games_labels.png ├── exercise_1 ├── teams.csv ├── exercise_1.css ├── solution │ ├── teams.csv │ ├── solution_1.css │ ├── index.html │ └── solution_1.js ├── index.html └── exercise_1.js ├── exercise_2 ├── teams.csv ├── exercise_2.css ├── solution │ ├── teams.csv │ ├── solution_2.css │ ├── index.html │ └── solution_2.js ├── index.html └── exercise_2.js ├── exercise_3 ├── teams.csv ├── exercise_3.css ├── solution │ ├── teams.csv │ ├── solution_3.css │ ├── index.html │ ├── solution_3.html │ └── solution_3.js ├── index.html └── exercise_3.js ├── index.html ├── preprocessing └── preprocessing.py ├── urls.js ├── bar.css ├── sortable.js ├── README.md └── mlb2018.csv /img/end_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/end_code.png -------------------------------------------------------------------------------- /img/exercise1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/exercise1.png -------------------------------------------------------------------------------- /img/g_element.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/g_element.png -------------------------------------------------------------------------------- /img/start_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/start_code.png -------------------------------------------------------------------------------- /img/create_rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/create_rect.png -------------------------------------------------------------------------------- /img/numerically.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/numerically.png -------------------------------------------------------------------------------- /img/alphabetically.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/alphabetically.png -------------------------------------------------------------------------------- /img/create_x_axis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/create_x_axis.png -------------------------------------------------------------------------------- /img/data_variable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/data_variable.png -------------------------------------------------------------------------------- /img/exercise1_sol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/exercise1_sol.png -------------------------------------------------------------------------------- /exercise_1/teams.csv: -------------------------------------------------------------------------------- 1 | team,value 2 | Boston,100 3 | Detroit,85 4 | New York,80 5 | Chicago,75 6 | Atlanta,30 7 | -------------------------------------------------------------------------------- /exercise_2/teams.csv: -------------------------------------------------------------------------------- 1 | team,value 2 | Boston,100 3 | Detroit,85 4 | New York,80 5 | Chicago,75 6 | Atlanta,30 7 | -------------------------------------------------------------------------------- /exercise_3/teams.csv: -------------------------------------------------------------------------------- 1 | team,value 2 | Boston,100 3 | Detroit,85 4 | New York,80 5 | Chicago,75 6 | Atlanta,30 7 | -------------------------------------------------------------------------------- /img/create_bar_element.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/create_bar_element.png -------------------------------------------------------------------------------- /img/team_logo_games_labels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/d3workshop/master/img/team_logo_games_labels.png -------------------------------------------------------------------------------- /exercise_1/exercise_1.css: -------------------------------------------------------------------------------- 1 | .label{ 2 | text-anchor: middle; 3 | } 4 | 5 | .barlabel { 6 | text-anchor: middle; 7 | } -------------------------------------------------------------------------------- /exercise_1/solution/teams.csv: -------------------------------------------------------------------------------- 1 | team,value 2 | Boston,100 3 | Detroit,85 4 | New York,80 5 | Chicago,75 6 | Atlanta,30 7 | -------------------------------------------------------------------------------- /exercise_2/exercise_2.css: -------------------------------------------------------------------------------- 1 | .label{ 2 | text-anchor: middle; 3 | } 4 | 5 | .barlabel { 6 | text-anchor: middle; 7 | } -------------------------------------------------------------------------------- /exercise_2/solution/teams.csv: -------------------------------------------------------------------------------- 1 | team,value 2 | Boston,100 3 | Detroit,85 4 | New York,80 5 | Chicago,75 6 | Atlanta,30 7 | -------------------------------------------------------------------------------- /exercise_3/exercise_3.css: -------------------------------------------------------------------------------- 1 | .label{ 2 | text-anchor: middle; 3 | } 4 | 5 | .barlabel { 6 | text-anchor: middle; 7 | } -------------------------------------------------------------------------------- /exercise_3/solution/teams.csv: -------------------------------------------------------------------------------- 1 | team,value 2 | Boston,100 3 | Detroit,85 4 | New York,80 5 | Chicago,75 6 | Atlanta,30 7 | -------------------------------------------------------------------------------- /exercise_1/solution/solution_1.css: -------------------------------------------------------------------------------- 1 | .label{ 2 | text-anchor: middle; 3 | } 4 | 5 | .barlabel { 6 | text-anchor: middle; 7 | } -------------------------------------------------------------------------------- /exercise_2/solution/solution_2.css: -------------------------------------------------------------------------------- 1 | .label{ 2 | text-anchor: middle; 3 | } 4 | 5 | .barlabel { 6 | text-anchor: middle; 7 | } -------------------------------------------------------------------------------- /exercise_3/solution/solution_3.css: -------------------------------------------------------------------------------- 1 | .label{ 2 | text-anchor: middle; 3 | } 4 | 5 | .barlabel { 6 | text-anchor: middle; 7 | } -------------------------------------------------------------------------------- /exercise_1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /exercise_2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /exercise_1/solution/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /exercise_3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 14 |
15 |
16 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /exercise_2/solution/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 14 |
15 |
16 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /exercise_3/solution/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 14 |
15 |
16 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /exercise_3/solution/solution_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 14 |
15 |
16 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /preprocessing/preprocessing.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Oct 18 16:17:58 2019 4 | 5 | @author: caoa 6 | """ 7 | import pandas as pd 8 | 9 | pd.options.display.max_rows =20 10 | pd.options.display.max_columns = 20 11 | 12 | df = pd.read_csv('GL2018.TXT', header=None, usecols=[0,3,6,9,10]) 13 | df.columns = ['date','away','home','aRuns','hRuns'] 14 | 15 | #%% 16 | df['team'] = df.apply(lambda x: x['away'] if x['aRuns'] > x['hRuns'] else x['home'], axis=1) 17 | data = df[['date','team']] 18 | data.to_csv('daily_snapshot.csv', index=False) 19 | 20 | #%% Find first day where all teams have won at least one game 21 | data['date'] = pd.to_datetime(data['date'], format='%Y%m%d') 22 | daterange = pd.date_range('2018-03-29','2018-10-01',freq='D') 23 | for day in daterange: 24 | abc = data[data['date'] <= day] 25 | xyz = abc.team.value_counts() 26 | if xyz.shape[0] >= 30: 27 | print(day) 28 | break 29 | -------------------------------------------------------------------------------- /urls.js: -------------------------------------------------------------------------------- 1 | const urls = { 2 | 'ARI':'Arizona_Diamondbacks', 3 | 'ATL':'Atlanta_Braves', 4 | 'SFN':'SanFrancisco_Giants', 5 | 'CHN':'Chicago_Cubs', 6 | 'NYN':'NewYork_Mets', 7 | 'MIL':'Milwaukee_Brewers', 8 | 'BAL':'Baltimore_Orioles', 9 | 'CHA':'Chicago_White_Sox', 10 | 'OAK':'Oakland_Athletics', 11 | 'SEA':'Seattle_Mariners', 12 | 'TBA':'TampaBay_Rays', 13 | 'HOU':'Houston_Astros', 14 | 'NYA':'NewYork_Yankees', 15 | 'PHI':'Philadelphia_Phillies', 16 | 'WAS':'Washington_Nationals', 17 | 'MIA':'Miami_Marlins', 18 | 'PIT':'Pittsburgh_Pirates', 19 | 'ANA':'LosAngeles_Angels', 20 | 'BOS':'Boston_Redsox', 21 | 'TEX':'Texas_Rangers', 22 | 'COL':'Colorado_Rockies', 23 | 'LAN':'LosAngeles_Dodgers', 24 | 'MIN':'Minnesota_Twins', 25 | 'CLE':'Cleveland_Indians', 26 | 'TOR':'Toronto_Blue_Jays', 27 | 'SLN':'StLouis_Cardinals', 28 | 'CIN':'Cincinnati_Reds', 29 | 'DET':'Detroit_Tigers', 30 | 'SDN':'SanDiego_Padres', 31 | 'KCA':'KansasCity_Royals', 32 | } -------------------------------------------------------------------------------- /bar.css: -------------------------------------------------------------------------------- 1 | /* .chart { 2 | clip-path: url(#clip); 3 | } */ 4 | 5 | .bar { 6 | fill: orange; 7 | } 8 | 9 | .x.axis text { 10 | font: 15px sans-serif; 11 | } 12 | 13 | .axis path, .axis line { 14 | fill: none; 15 | stroke: '#000'; 16 | shape-rendering: crispEdges; 17 | } 18 | 19 | .label { 20 | text-anchor: middle; 21 | font: 20px helvetica; 22 | } 23 | 24 | #date { 25 | text-anchor: start; 26 | font: 20px helvetica; 27 | } 28 | 29 | .grid line { 30 | stroke: lightgrey; 31 | stroke-opacity: 0.7; 32 | shape-rendering: crispEdges; 33 | } 34 | 35 | .grid path { 36 | stroke-width: 0; 37 | } 38 | 39 | .team { 40 | fill: black; 41 | font: 14px sans-serif; 42 | text-anchor: end; 43 | font-weight: 600; 44 | } 45 | 46 | .barlabel{ 47 | fill: black; 48 | font: 14px sans-serif; 49 | text-anchor: left; 50 | font-weight: 600; 51 | } 52 | 53 | .logo { 54 | fill: black; 55 | font: 14px sans-serif; 56 | text-anchor: middle; 57 | } 58 | 59 | .divisions { 60 | stroke: black; 61 | stroke-width: 2; 62 | stroke-dasharray: 12; 63 | } -------------------------------------------------------------------------------- /exercise_2/exercise_2.js: -------------------------------------------------------------------------------- 1 | // set the dimensions and margins of the graph 2 | var outerWidth = 960; 3 | var outerHeight = 500; 4 | 5 | var margin = {top: 50, right: 20, bottom: 80, left: 80}, 6 | width = outerWidth - margin.left - margin.right, 7 | height = outerHeight - margin.top - margin.bottom; 8 | 9 | // set the ranges 10 | var x = d3.scaleBand() 11 | .range([0, width]) 12 | .padding(0.33); 13 | 14 | var y= d3.scaleLinear() 15 | .range([height, 0]); 16 | 17 | 18 | var xAxis = d3.axisTop(x) 19 | .ticks(5) 20 | 21 | var yAxis = d3.axisLeft(y) 22 | .tickFormat('') 23 | 24 | // append the svg object to the body of the page 25 | // append a 'group' element to 'svg' 26 | // moves the 'group' element to the top left margin 27 | var svg = d3.select('body').append('svg') 28 | .attr("class", "chart") 29 | .attr("width", outerWidth) 30 | .attr("height", outerHeight) 31 | .append("g") 32 | .attr("transform", `translate(${margin.left},${margin.top})`); 33 | 34 | // data 35 | var data = [{'team':'Boston','value':100}, 36 | {'team':'Detroit','value':85}, 37 | {'team':'New York','value':80}, 38 | {'team':'Atlanta','value':75}, 39 | {'team':'Chicago','value':30}] 40 | 41 | 42 | // scale the range of the data in the domains 43 | x.domain(data.map(d => d.team)); 44 | y.domain([0, d3.max(data, d => d.value)]) 45 | 46 | 47 | // append the rectangles for the bar chart 48 | var bar = svg.selectAll(".bar") 49 | .data(data) 50 | .join("g") 51 | .attr("class","bar") 52 | 53 | 54 | 55 | var rect = bar.append('rect') 56 | .attr("height", d => height - y(d.value)) 57 | .attr("x", d => x(d.team)) 58 | .attr("width", x.bandwidth()) 59 | .attr("y", d => y(d.value)) 60 | .style('fill', d => d3.interpolatePurples(d.value/100)); 61 | 62 | // add the x Axis 63 | svg.append("g") 64 | .attr("transform", `translate(0, ${height})`) 65 | .call(d3.axisBottom(x)); 66 | 67 | // add the y Axis 68 | svg.append("g") 69 | .call(d3.axisLeft(y)); 70 | 71 | // add chart labels 72 | labels = svg.append('g') 73 | .attr('class', 'label') 74 | 75 | // x label 76 | labels.append('text') 77 | .attr('transform', `translate(${width/2},450)`) 78 | .text('Teams') 79 | 80 | // y label 81 | ylabel = labels.append('text') 82 | .attr('transform', `translate(-45,${height/2}) rotate(-90)`) 83 | .text('Wins') 84 | 85 | barLabels = bar.append('text') 86 | .attr('class', 'barlabel') 87 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 88 | .attr('y', d => y(d.value) - 15) 89 | .text(d => d.value) 90 | .style('fill', 'black') 91 | -------------------------------------------------------------------------------- /exercise_1/solution/solution_1.js: -------------------------------------------------------------------------------- 1 | // set the dimensions and margins of the graph 2 | var outerWidth = 960; 3 | var outerHeight = 500; 4 | 5 | var margin = {top: 50, right: 20, bottom: 80, left: 80}, 6 | width = outerWidth - margin.left - margin.right, 7 | height = outerHeight - margin.top - margin.bottom; 8 | 9 | // set the ranges 10 | var x = d3.scaleBand() 11 | .range([0, width]) 12 | .padding(0.33); 13 | 14 | var y= d3.scaleLinear() 15 | .range([height, 0]); 16 | 17 | 18 | var xAxis = d3.axisTop(x) 19 | .ticks(5) 20 | 21 | var yAxis = d3.axisLeft(y) 22 | .tickFormat('') 23 | 24 | // append the svg object to the body of the page 25 | // append a 'group' element to 'svg' 26 | // moves the 'group' element to the top left margin 27 | var svg = d3.select('body').append('svg') 28 | .attr("class", "chart") 29 | .attr("width", outerWidth) 30 | .attr("height", outerHeight) 31 | .append("g") 32 | .attr("transform", `translate(${margin.left},${margin.top})`); 33 | 34 | // data 35 | var data = [{'team':'Boston','value':100}, 36 | {'team':'Detroit','value':85}, 37 | {'team':'New York','value':80}, 38 | {'team':'Atlanta','value':75}, 39 | {'team':'Chicago','value':30}] 40 | 41 | 42 | // scale the range of the data in the domains 43 | x.domain(data.map(d => d.team)); 44 | y.domain([0, d3.max(data, d => d.value)]) 45 | 46 | 47 | // append the rectangles for the bar chart 48 | var bar = svg.selectAll(".bar") 49 | .data(data) 50 | .join("g") 51 | .attr("class","bar") 52 | 53 | 54 | 55 | var rect = bar.append('rect') 56 | .attr("height", d => height - y(d.value)) 57 | .attr("x", d => x(d.team)) 58 | .attr("width", x.bandwidth()) 59 | .attr("y", d => y(d.value)) 60 | .style('fill', d => d3.interpolatePurples(d.value/100)); 61 | 62 | // add the x Axis 63 | svg.append("g") 64 | .attr("transform", `translate(0, ${height})`) 65 | .call(d3.axisBottom(x)); 66 | 67 | // add the y Axis 68 | svg.append("g") 69 | .call(d3.axisLeft(y)); 70 | 71 | // add chart labels 72 | labels = svg.append('g') 73 | .attr('class', 'label') 74 | 75 | // x label 76 | labels.append('text') 77 | .attr('transform', `translate(${width/2},450)`) 78 | .text('Teams') 79 | 80 | // y label 81 | ylabel = labels.append('text') 82 | .attr('transform', `translate(-45,${height/2}) rotate(-90)`) 83 | .text('Wins') 84 | 85 | barLabels = bar.append('text') 86 | .attr('class', 'barlabel') 87 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 88 | .attr('y', d => y(d.value) - 15) 89 | .text(d => d.value) 90 | .style('fill', 'black') 91 | -------------------------------------------------------------------------------- /exercise_1/exercise_1.js: -------------------------------------------------------------------------------- 1 | // set the dimensions and margins of the graph 2 | var outerWidth = 650; 3 | var outerHeight = 300; 4 | 5 | var margin = {top: 20, right: 20, bottom: 70, left: 100}, 6 | width = outerWidth - margin.left - margin.right - 20, 7 | height = outerHeight - margin.top - margin.bottom; 8 | 9 | // set the ranges 10 | var x = d3.scaleLinear() 11 | .range([0, width]); 12 | 13 | var y = d3.scaleBand() 14 | .range([height, 0]) 15 | .padding(0.33); 16 | 17 | var xAxis = d3.axisTop(x) 18 | .ticks(5) 19 | 20 | var yAxis = d3.axisLeft(y) 21 | .tickFormat('') 22 | 23 | // append the svg object to the body of the page 24 | // append a 'group' element to 'svg' 25 | // moves the 'group' element to the top left margin 26 | var svg = d3.select('body').append('svg') 27 | .attr("class", "chart") 28 | .attr("width", outerWidth) 29 | .attr("height", outerHeight) 30 | .append("g") 31 | .attr("transform", `translate(${margin.left},${margin.top})`); 32 | 33 | // data 34 | var data = [{'team':'Boston','value':100}, 35 | {'team':'Detroit','value':85}, 36 | {'team':'New York','value':80}, 37 | {'team':'Atlanta','value':75}, 38 | {'team':'Chicago','value':30}] 39 | 40 | 41 | // scale the range of the data in the domains 42 | x.domain([0, d3.max(data, d => d.value)]) 43 | y.domain(data.map(d => d.team)); 44 | 45 | 46 | // append the rectangles for the bar chart 47 | var bar = svg.selectAll(".bar") 48 | .data(data) 49 | .join("g") 50 | .attr("class","bar") 51 | 52 | 53 | 54 | var rect = bar.append('rect') 55 | .attr("width", d => x(d.value)) 56 | .attr("y", d => y(d.team)) 57 | .attr("height", y.bandwidth()) 58 | 59 | .style('fill', d => d3.interpolatePurples(d.value/100)) 60 | 61 | // add the x Axis 62 | svg.append("g") 63 | .attr("transform", `translate(0, ${height})`) 64 | .call(d3.axisBottom(x)); 65 | 66 | // add the y Axis 67 | svg.append("g") 68 | .call(d3.axisLeft(y)); 69 | 70 | // add chart labels 71 | labels = svg.append('g') 72 | .attr('class', 'label') 73 | 74 | // x label 75 | labels.append('text') 76 | .attr('transform', `translate(${width/2},250)`) 77 | .text('Wins') 78 | 79 | // y label 80 | ylabel = labels.append('text') 81 | .attr('transform', `translate(-65,${height/2}) rotate(-90)`) 82 | .text('Teams') 83 | 84 | barLabels = bar.append('text') 85 | .attr('class', 'barlabel') 86 | .attr('x', d => x(d.value) - 20) 87 | .attr('y', d => y(d.team) + (y.bandwidth()/2) + 4) 88 | .text(d => d.value) 89 | .style('fill', 'black') 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /exercise_3/exercise_3.js: -------------------------------------------------------------------------------- 1 | // set the dimensions and margins of the graph 2 | var outerWidth = 960; 3 | var outerHeight = 500; 4 | 5 | var margin = {top: 50, right: 20, bottom: 80, left: 80}, 6 | width = outerWidth - margin.left - margin.right, 7 | height = outerHeight - margin.top - margin.bottom; 8 | 9 | // set the ranges 10 | var y= d3.scaleLinear() 11 | .range([height, 0]); 12 | 13 | var x = d3.scaleBand() 14 | .range([0, width]) 15 | .padding(0.33); 16 | 17 | var xAxis = d3.axisTop(x) 18 | .ticks(5) 19 | 20 | var yAxis = d3.axisLeft(y) 21 | .tickFormat('') 22 | 23 | // append the svg object to the body of the page 24 | // append a 'group' element to 'svg' 25 | // moves the 'group' element to the top left margin 26 | var svg = d3.select('body').append('svg') 27 | .attr("class", "chart") 28 | .attr("width", outerWidth) 29 | .attr("height", outerHeight) 30 | .append("g") 31 | .attr("transform", `translate(${margin.left},${margin.top})`); 32 | 33 | // data 34 | var data = [{'team':'Boston','value':100}, 35 | {'team':'Detroit','value':85}, 36 | {'team':'New York','value':80}, 37 | {'team':'Atlanta','value':75}, 38 | {'team':'Chicago','value':30}] 39 | 40 | 41 | // scale the range of the data in the domains 42 | y.domain([0, d3.max(data, d => d.value)]) 43 | x.domain(data.map(d => d.team)); 44 | 45 | 46 | 47 | // append the rectangles for the bar chart 48 | var bar = svg.selectAll(".bar") 49 | .data(data) 50 | .join("g") 51 | .attr("class","bar") 52 | 53 | 54 | var rect = bar.append('rect') 55 | .attr("height", d => height - y(d.value)) 56 | .attr("x", d => x(d.team)) 57 | .attr("width", x.bandwidth()) 58 | .attr("y", d => y(d.value)) 59 | .style('fill', d => d3.interpolatePurples(d.value/100)); 60 | 61 | 62 | // add the x Axis 63 | svg.append("g") 64 | .attr('class', 'xaxis') 65 | .attr("transform", `translate(0, ${height})`) 66 | .call(d3.axisBottom(x)); 67 | 68 | // add the y Axis 69 | svg.append("g") 70 | .call(d3.axisLeft(y)); 71 | 72 | // add chart labels 73 | labels = svg.append('g') 74 | .attr('class', 'label') 75 | 76 | // x label 77 | labels.append('text') 78 | .attr('transform', `translate(${width/2},450)`) 79 | .text('Teams') 80 | 81 | // y label 82 | ylabel = labels.append('text') 83 | .attr('transform', `translate(-45,${height/2}) rotate(-90)`) 84 | .text('Wins') 85 | 86 | barLabels = bar.append('text') 87 | .attr('class', 'barlabel') 88 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 89 | .attr('y', d => y(d.value) - 15) 90 | .text(d => d.value) 91 | .style('fill', 'black') 92 | 93 | 94 | function updateAlpha() { 95 | 96 | x.domain((data.map(d => d.team)).sort()); 97 | 98 | bar.selectAll('rect') 99 | .attr("x", d => x(d.team)) 100 | 101 | svg.select(".xaxis") 102 | .call(d3.axisBottom(x)); 103 | 104 | 105 | bar.selectAll('.barlabel') 106 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 107 | 108 | } 109 | 110 | 111 | function updateNum() { 112 | 113 | data.sort((a,b) => d3.ascending(a.value, b.value)) 114 | 115 | x.domain(data.map(d => d.team)); 116 | 117 | bar.selectAll('rect') 118 | .attr("x", d => x(d.team)) 119 | 120 | svg.select(".xaxis") 121 | .call(d3.axisBottom(x)); 122 | 123 | bar.selectAll('.barlabel') 124 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 125 | 126 | } 127 | -------------------------------------------------------------------------------- /exercise_2/solution/solution_2.js: -------------------------------------------------------------------------------- 1 | // set the dimensions and margins of the graph 2 | var outerWidth = 960; 3 | var outerHeight = 500; 4 | 5 | var margin = {top: 50, right: 20, bottom: 80, left: 80}, 6 | width = outerWidth - margin.left - margin.right, 7 | height = outerHeight - margin.top - margin.bottom; 8 | 9 | // set the ranges 10 | var x = d3.scaleBand() 11 | .range([0, width]) 12 | .padding(0.33); 13 | 14 | var y= d3.scaleLinear() 15 | .range([height, 0]); 16 | 17 | 18 | var xAxis = d3.axisTop(x) 19 | .ticks(5) 20 | 21 | var yAxis = d3.axisLeft(y) 22 | .tickFormat('') 23 | 24 | // append the svg object to the body of the page 25 | // append a 'group' element to 'svg' 26 | // moves the 'group' element to the top left margin 27 | var svg = d3.select('body').append('svg') 28 | .attr("class", "chart") 29 | .attr("width", outerWidth) 30 | .attr("height", outerHeight) 31 | .append("g") 32 | .attr("transform", `translate(${margin.left},${margin.top})`); 33 | 34 | // data 35 | var data = [{'team':'Boston','value':100}, 36 | {'team':'Detroit','value':85}, 37 | {'team':'New York','value':80}, 38 | {'team':'Atlanta','value':75}, 39 | {'team':'Chicago','value':30}] 40 | 41 | 42 | // scale the range of the data in the domains 43 | x.domain(data.map(d => d.team)); 44 | y.domain([0, d3.max(data, d => d.value)]) 45 | 46 | 47 | // append the rectangles for the bar chart 48 | var bar = svg.selectAll(".bar") 49 | .data(data) 50 | .join("g") 51 | .attr("class","bar") 52 | 53 | 54 | var rect = bar.append('rect') 55 | .attr("height", d => height - y(d.value)) 56 | .attr("x", d => x(d.team)) 57 | .attr("width", x.bandwidth()) 58 | .attr("y", d => y(d.value)) 59 | .style('fill', d => d3.interpolatePurples(d.value/100)); 60 | 61 | 62 | // add the x Axis 63 | svg.append("g") 64 | .attr('class', 'xaxis') 65 | .attr("transform", `translate(0, ${height})`) 66 | .call(d3.axisBottom(x)); 67 | 68 | // add the y Axis 69 | svg.append("g") 70 | .call(d3.axisLeft(y)); 71 | 72 | // add chart labels 73 | labels = svg.append('g') 74 | .attr('class', 'label') 75 | 76 | // x label 77 | labels.append('text') 78 | .attr('transform', `translate(${width/2},450)`) 79 | .text('Teams') 80 | 81 | // y label 82 | ylabel = labels.append('text') 83 | .attr('transform', `translate(-45,${height/2}) rotate(-90)`) 84 | .text('Wins') 85 | 86 | barLabels = bar.append('text') 87 | .attr('class', 'barlabel') 88 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 89 | .attr('y', d => y(d.value) - 15) 90 | .text(d => d.value) 91 | .style('fill', 'black') 92 | 93 | 94 | function updateAlpha() { 95 | 96 | x.domain((data.map(d => d.team)).sort()); 97 | 98 | bar.selectAll('rect') 99 | .attr("x", d => x(d.team)) 100 | 101 | svg.select(".xaxis") 102 | .call(d3.axisBottom(x)); 103 | 104 | 105 | bar.selectAll('.barlabel') 106 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 107 | 108 | 109 | 110 | } 111 | 112 | function updateNum() { 113 | 114 | data.sort((a,b) => d3.ascending(a.value, b.value)) 115 | 116 | x.domain(data.map(d => d.team)); 117 | 118 | bar.selectAll('rect') 119 | .attr("x", d => x(d.team)) 120 | 121 | svg.select(".xaxis") 122 | .call(d3.axisBottom(x)); 123 | 124 | bar.selectAll('.barlabel') 125 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 126 | 127 | } 128 | -------------------------------------------------------------------------------- /exercise_3/solution/solution_3.js: -------------------------------------------------------------------------------- 1 | // set the dimensions and margins of the graph 2 | var outerWidth = 960; 3 | var outerHeight = 500; 4 | 5 | var margin = {top: 50, right: 20, bottom: 80, left: 80}, 6 | width = outerWidth - margin.left - margin.right, 7 | height = outerHeight - margin.top - margin.bottom; 8 | 9 | // set the ranges 10 | var y= d3.scaleLinear() 11 | .range([height, 0]); 12 | 13 | var x = d3.scaleBand() 14 | .range([0, width]) 15 | .padding(0.33); 16 | 17 | var xAxis = d3.axisTop(x) 18 | .ticks(5) 19 | 20 | var yAxis = d3.axisLeft(y) 21 | .tickFormat('') 22 | 23 | // append the svg object to the body of the page 24 | // append a 'group' element to 'svg' 25 | // moves the 'group' element to the top left margin 26 | var svg = d3.select('body').append('svg') 27 | .attr("class", "chart") 28 | .attr("width", outerWidth) 29 | .attr("height", outerHeight) 30 | .append("g") 31 | .attr("transform", `translate(${margin.left},${margin.top})`); 32 | 33 | // data 34 | var data = [{'team':'Boston','value':100}, 35 | {'team':'Detroit','value':85}, 36 | {'team':'New York','value':80}, 37 | {'team':'Atlanta','value':75}, 38 | {'team':'Chicago','value':30}] 39 | 40 | 41 | // scale the range of the data in the domains 42 | y.domain([0, d3.max(data, d => d.value)]) 43 | x.domain(data.map(d => d.team)); 44 | 45 | 46 | // append the rectangles for the bar chart 47 | var bar = svg.selectAll(".bar") 48 | .data(data) 49 | .join("g") 50 | .attr("class","bar") 51 | 52 | 53 | var rect = bar.append('rect') 54 | .attr("height", d => height - y(d.value)) 55 | .attr("x", d => x(d.team)) 56 | .attr("width", x.bandwidth()) 57 | .attr("y", d => y(d.value)) 58 | .style('fill', d => d3.interpolatePurples(d.value/100)); 59 | 60 | 61 | // add the x Axis 62 | svg.append("g") 63 | .attr('class', 'xaxis') 64 | .attr("transform", `translate(0, ${height})`) 65 | .call(d3.axisBottom(x)); 66 | 67 | // add the y Axis 68 | svg.append("g") 69 | .call(d3.axisLeft(y)); 70 | 71 | // add chart labels 72 | labels = svg.append('g') 73 | .attr('class', 'label') 74 | 75 | // x label 76 | labels.append('text') 77 | .attr('transform', `translate(${width/2},450)`) 78 | .text('Teams') 79 | 80 | // y label 81 | ylabel = labels.append('text') 82 | .attr('transform', `translate(-45,${height/2}) rotate(-90)`) 83 | .text('Wins') 84 | 85 | barLabels = bar.append('text') 86 | .attr('class', 'barlabel') 87 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 88 | .attr('y', d => y(d.value) - 15) 89 | .text(d => d.value) 90 | .style('fill', 'black') 91 | 92 | 93 | function updateAlpha() { 94 | const T = 500 95 | 96 | x.domain((data.map(d => d.team)).sort()); 97 | 98 | bar.selectAll('rect') 99 | .transition().duration(T) 100 | .attr("x", d => x(d.team)) 101 | 102 | svg.select(".xaxis") 103 | .transition().duration(T) 104 | .call(d3.axisBottom(x)) 105 | 106 | bar.selectAll('.barlabel') 107 | .transition().duration(T) 108 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 109 | 110 | 111 | } 112 | 113 | function updateNum() { 114 | const T = 500 115 | 116 | data.sort((a,b) => d3.ascending(a.value, b.value)); 117 | 118 | x.domain(data.map(d => d.team)); 119 | 120 | bar.selectAll('rect') 121 | .transition().duration(T) 122 | .attr("x", d => x(d.team)) 123 | 124 | svg.select(".xaxis") 125 | .transition().duration(T) 126 | .call(d3.axisBottom(x)) 127 | 128 | bar.selectAll('.barlabel') 129 | .transition().duration(T) 130 | .attr('x', d => x(d.team) + (x.bandwidth()/2)) 131 | 132 | } 133 | 134 | -------------------------------------------------------------------------------- /sortable.js: -------------------------------------------------------------------------------- 1 | async function createChart() { 2 | 3 | // read data 4 | const fileLocation = 'https://gist.githubusercontent.com/caocscar/8cdb75721ea4f6c8a032a00ebc73516c/raw/854bbee2faffb4f6947b6b6c2424b18ca5a8970e/mlb2018.csv' 5 | DATA = await d3.csv(fileLocation, type) 6 | let chartDate = new Date(2018,3,3) 7 | let data = filterData(chartDate) 8 | 9 | // margins 10 | let margin = {top: 80, right: 90, bottom: 30+50, left: 120}, 11 | width = 900 - margin.left - margin.right, 12 | height = 1500 - margin.top - margin.bottom; // 760 13 | 14 | // svg setup 15 | let svg = d3.select('body').append('svg') 16 | .attr("class", "chart") 17 | .attr("width", width + margin.left + margin.right) 18 | .attr("height", height + margin.top + margin.bottom) 19 | .append("g") 20 | .attr("transform", `translate(${margin.left},${margin.top})`); 21 | 22 | // set up scales 23 | let y = d3.scaleBand() 24 | .domain(data.map(d => d.team).reverse()) 25 | .range([height, 0]) 26 | .padding(0.33) 27 | 28 | let x = d3.scaleLinear() 29 | .domain([0, Math.ceil(d3.max(data, d => d.value)/5)*5]) 30 | .range([0, width]); 31 | 32 | // add axes 33 | let xAxis = d3.axisTop(x) 34 | .ticks(6) 35 | 36 | svg.append("g") 37 | .attr("class", "x axis") 38 | .call(xAxis); 39 | 40 | let yAxis = d3.axisLeft(y) 41 | .tickFormat('') 42 | 43 | svg.append("g") 44 | .attr("class", "y axis") 45 | .call(yAxis); 46 | 47 | // add the x-axis gridlines 48 | let gridlines = d3.axisTop(x) 49 | .ticks(6) 50 | .tickSize(-height) 51 | .tickFormat("") 52 | 53 | svg.append("g") 54 | .attr("class", "grid") 55 | .call(gridlines) 56 | 57 | // set up bar groups 58 | let bar = svg.selectAll(".bar") 59 | .data(data) 60 | .join("g") 61 | .attr("class", "bar") 62 | .attr("transform", d => `translate(0,${y(d.team)})`) 63 | 64 | // adding bars 65 | let rects = bar.append('rect') 66 | .attr("width", (d,i) => x(d.value)) 67 | .attr("height", y.bandwidth()) 68 | .style('fill', d => d3.interpolateRdYlBu(d.value/100)) 69 | 70 | // team labels 71 | bar.append('text') 72 | .attr('class', 'team') 73 | .attr('x', -10) 74 | .attr('y', y.bandwidth()/2 + 5) 75 | .text(d => d.team) 76 | 77 | // team logos 78 | const imgsize = 40 79 | let imgs = bar.append("svg:image") 80 | .attr('class', 'logo') 81 | .attr('x', d => x(d.value) + 5) 82 | .attr('y', -5) 83 | .attr('width', imgsize) 84 | .attr('height', imgsize) 85 | .attr("xlink:href", d => `http://www.capsinfo.com/images/MLB_Team_Logos/${urls[d.team]}.png`) 86 | 87 | // bar labels 88 | let barLabels = bar.append('text') 89 | .attr('class', 'barlabel') 90 | .attr('x', d => x(d.value) + 10 + imgsize) 91 | .attr('y', y.bandwidth()/2 + 5) 92 | .text(d => d.value) 93 | 94 | // other chart labels 95 | labels = svg.append('g') 96 | .attr('class', 'label') 97 | 98 | // x label 99 | labels.append('text') 100 | .attr('transform', `translate(${width},-40)`) 101 | .text('Wins') 102 | 103 | // y label 104 | ylabel = labels.append('text') 105 | .attr('transform', `translate(-80,${height/2}) rotate(-90)`) // order matters 106 | .text('Teams') 107 | 108 | // date label 109 | const formatDate = d3.timeFormat('%b %-d') 110 | let dateLabel = labels.append('text') 111 | .attr('id', 'date') 112 | .attr('transform', 'translate(0,-40)') 113 | .text(formatDate(chartDate)) 114 | 115 | labels.append('text') 116 | .attr('id', 'season') 117 | .attr('transform', `translate(${width/2},-40)`) 118 | .text('MLB 2018 Season') 119 | 120 | // clipping rectangle 121 | const z = 0.97*(height / data.length) 122 | d3.select('.chart').append("defs") 123 | .append("clipPath") 124 | .attr("id", "clip") 125 | .append("rect") 126 | .attr('x', 0) 127 | .attr('y', 0) 128 | .attr("width", width + margin.left + margin.right) 129 | .attr("height", 0.4*height) 130 | 131 | // sorting transition 132 | const T = 300 133 | let dailyUpdate = setInterval(function() { 134 | 135 | chartDate = d3.timeDay.offset(chartDate,1) 136 | dateLabel.text(formatDate(chartDate)) 137 | data = filterData(chartDate) 138 | 139 | // update x-axis 140 | x.domain([0, Math.ceil(d3.max(data, d => d.value)/5)*5]); 141 | svg.select('.x.axis').transition().duration(T) 142 | .call(xAxis); 143 | svg.select('.grid').transition().duration(T) 144 | .call(gridlines); 145 | 146 | // update bar chart 147 | rects.data(data) 148 | .transition().duration(T) 149 | .attr("width", d => x(d.value)) 150 | .style('fill', d => d3.interpolateRdYlBu(d.value/100)) 151 | imgs.data(data) 152 | .transition().duration(T) 153 | .attr('x', d => x(d.value) + 5) 154 | barLabels.data(data) 155 | .transition().duration(T) 156 | .attr('x', d => x(d.value) + 10 + imgsize) 157 | .attr('y', y.bandwidth()/2 + 5) 158 | .text(d => d.value) 159 | 160 | // sort data 161 | data.sort((a,b) => d3.descending(a.value,b.value)); 162 | 163 | // update y-axis 164 | y.domain(data.map(d => d.team).reverse()); 165 | bar.transition().duration(T) 166 | .attr("transform", d => `translate(0,${y(d.team)})`) 167 | 168 | // exit function 169 | if (chartDate > new Date(2018,9,1)) { 170 | clearInterval(dailyUpdate) 171 | } 172 | 173 | }, T); 174 | 175 | } 176 | 177 | function type(d) { 178 | const formatDate = d3.timeParse('%Y%m%d') 179 | d.date = formatDate(d.date) 180 | return d 181 | } 182 | 183 | function filterData(chartDate) { 184 | const snapshot = DATA.filter(d => d.date <= chartDate) 185 | const wins = d3.rollup(snapshot, v => v.length, d => d.team) // returns Map object 186 | return Array.from(wins, ([key, value]) => ({'team':key, 'value':value})) 187 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # D3.js Workshop 2 | - [Introduction to D3](#introduction-to-d3) 3 | - [Key Components](#key-components) 4 | - [Getting Started](#getting-started) 5 | - [Running D3 Locally](#running-d3-locally) 6 | - [Getting D3](#getting-d3) 7 | - [D3 Version](#d3-version) 8 | - [HTML Setup](#html-setup) 9 | - [Graph Setup](#graph-setup) 10 | - [Reading in Data](#reading-in-data) 11 | - [Setting up D3 Scales](#setting-up-d3-scales) 12 | - [Adding Axes](#adding-axes) 13 | - [Individual Team Bar Charts](#individual-team-bar-charts) 14 | - [Exercise #1 (Vertical Bar Chart)](#exercise-1-vertical-bar-chart) 15 | - [Animating the Graph](#animating-the-graph) 16 | - [Exercise #2 (Sort the Chart)](#exercise-2-sort-the-chart) 17 | - [Exercise #3 (Animated Sort)](#exercise-3-animated-sort) 18 | - [Easing](#easing) 19 | - [Clipped Path](#clipped-path) 20 | - [References](#references) 21 | ## Introduction to D3 22 | D3 (Data-Driven Documents or D3.js) is a JavaScript library for manipulating documents based on data and is used in conjunction with tools like HTML, SVG, and CSS. It's used by the [New York Times](https://getdolphins.com/blog/interactive-data-visualizations-new-york-times/) to make interactive custom graphics for its [news](https://www.nytimes.com/interactive/2019/11/06/us/politics/elizabeth-warren-policies-taxes.html) [articles](https://www.nytimes.com/interactive/2018/03/27/upshot/make-your-own-mobility-animation.html). 23 | 24 | ### Key Components 25 | - HTML (HyperText Markup Language) 26 | - standard markup language for webpages 27 | - defines content 28 | - CSS (Cascading Style Sheets) 29 | - language to describe the style of a HTML document 30 | - describes how HTML elements should be displayed 31 | - JavaScript 32 | - scripting language for web pages 33 | - lightweight, interpreted, or just-in-time compiled programming language 34 | - SVG (Scalable Vector Graphics) 35 | - language for describing 2-D vector graphics in XML 36 | - Web Server 37 | 38 | ## Getting Started 39 | Download the files from the Github repo or the Box link provided in the workshop. The main files we will be working with are `index.html`, `sortable.js`, and `bar.css`. 40 | 41 | ## Running D3 Locally 42 | To run D3 locally on your PC, you need to set up a web server. Fortunately, Python makes this relatively easy. Open a terminal (i.e. Anaconda Prompt) that has access to Python and run a simple http server with the command `python -m http.server `. The port number is optional (default is 8000). Then open your browser and go to `localhost:8000` or `127.0.0.1:8000`. 43 | 44 | ## Getting D3 45 | We load the d3.js library from a CDN with the following snippet. 46 | ```html 47 | 48 | ``` 49 | 50 | We'll also use the **d3-array** library to do some data wrangling to get the data in the right format for plotting. 51 | ```html 52 | 53 | ``` 54 | 55 | ### D3 Version 56 | We're using D3 version 5. Most of the online v5 examples are written using something called [Observable notebooks](https://observablehq.com/) (think of it like Jupyter Notebooks for JavaScript). The syntax for Observable notebooks is slightly different than what you would use for HTML. Most of the other examples on the web are for v3 or v4. Ideally, you'll want to look for examples using v4 or v5 on the web. There were some breaking changes made in the conversion from v3 to v4. Its not impossible to figure out from v3 examples but its just more errors to debug. 57 | 58 | ## HTML Setup 59 | Let's take a quick peek at our HTML file. Its pretty bare bones. The things to note are: 60 | - loading two JavaScript files `urls.js` and `sortable.js` 61 | - loading one CSS file `bar.css` 62 | - one function call `createChart()` which will create our chart for us within the `` tag 63 | 64 | ```html 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | ``` 80 | This is what you would see if you right-click *View page source Ctrl+U*. Note that this is different than what you would see if you inspected the Elements tab in Chrome using your browser. 81 | 82 | ## Graph Setup 83 | Now, let's move onto our JavaScript file `sortable.js` and create the function `createChart` that we're going to call. We need to first set up our graph. We start by specifying the dimensions and margins of our graph. The standard D3 convention for setting up margins can be found at https://bl.ocks.org/mbostock/3019563 84 | 85 | Let us follow along with our code. 86 | 87 | First define the `margin` object with properties for the four sides: 88 | ```javascript 89 | let margin = {top: 80, right: 90, bottom: 30+50, left: 120} 90 | ``` 91 | 92 | Next define `width` and `height`as the inner dimensions of the chart area: 93 | ```javascript 94 | width = 900 - margin.left - margin.right 95 | height = 1500 - margin.top - margin.bottom 96 | ``` 97 | 98 | Lastly, define a `svg` element with three attributes (`class`, `width`, and `height`) and translate its origin to the top-left corner of the chart area with a `g` element. 99 | ```javascript 100 | let svg = d3.select('body').append('svg') 101 | .attr("class", "chart") 102 | .attr("width", width + margin.left + margin.right) 103 | .attr("height", height + margin.top + margin.bottom) 104 | .append("g") 105 | .attr("transform", "translate(${margin.left},${margin.top})") 106 | ``` 107 | Let's breakdown what this D3 code block is doing. 108 | - The first line selects the `` tag in the HTML and appends (or nests) a `svg` element within the `` element. 109 | - The next three lines define attributes for the `svg` element. 110 | - The second-to-last line appends a `g` element to `svg`. 111 | - The last line applies a transformation (a translation) to the `g` element. 112 | 113 | **Note**: There is a D3 distinction between a 2 space and 4 space indentation. Two space indentation means you are returning a new selection and 4 space indentation means working with an existing selection. Don't worry if that means nothing to you at the moment. Just know that its intentional. 114 | 115 | ## Reading in Data 116 | We will be looking at data from Major League Baseball 2018 season and the accumulation of wins by each team as the season progresses. 117 | 118 | The data resides in a Github gist. There is also a copy in our folder but I wanted to show you that you can also read files from the web. 119 | ```javascript 120 | const fileLocation = 'https://gist.githubusercontent.com/caocscar/8cdb75721ea4f6c8a032a00ebc73516c/raw/854bbee2faffb4f6947b6b6c2424b18ca5a8970e/mlb2018.csv' 121 | ``` 122 | 123 | Next we will read the file, parse it, convert it into an array of objects (line 1) and filter it by date using our custom `filterData` function (lines 2 & 3). I chose April 4th as the start date as every team has won at least one game by then (helping avoid some other complications with adding teams dynamically). 124 | ```javascript 125 | DATA = await d3.csv(fileLocation, type) 126 | let chartDate = new Date(2018,3,3) 127 | let data = filterData(chartDate) 128 | ``` 129 | **Note**: JavaScript starts month at index 0. 130 | 131 | The function `type` takes in the data and parses the date strings into a JavaScript `Date` format. You can think of `d` as a row of the data. 132 | ```javascript 133 | function type(d) { 134 | const formatDate = d3.timeParse('%Y%m%d') 135 | d.date = formatDate(d.date) 136 | return d 137 | } 138 | ``` 139 | **Note**: `d3.csv` reads in all columns as strings and you usually convert them to numeric using a `type` function. There is a `d3.autoType` function which is also available to do automatic conversions. 140 | 141 | The `filterData` function filters the data up to the given date. Here I'm using arrow `=>` functions for brevity. They are similar to `lambda` functions in Python. 142 | ```javascript 143 | function filterData(chartDate) { 144 | const snapshot = DATA.filter(d => d.date <= chartDate) 145 | const wins = d3.rollup(snapshot, v => v.length, d => d.team) 146 | return Array.from(wins, ([key, value]) => ({'team':key, 'value':value})) 147 | } 148 | ``` 149 | The function does some data wrangling for us. 150 | 1. Filters the data by date `DATA.filter(d => d.date <= chartDate)`. 151 | 2. Performs a groupby operation by team and counts how many times they appear (or win) in the data `d3.rollup(snapshot, v => v.length, d => d.team)`. 152 | 3. Returns the data in the desired format for us (an `Array` of JavaScript Objects) `Array.from(wins, ([key, value]) => ({'team':key, 'value':value}))`. 153 | 154 | I could have done the data wrangling in another language like Python or R and created a different dataset to be read in but wanted to show you that D3 and JavaScript can also do similar things. Our data should look like this after being returned by `filterData`. 155 | ![data variable](img/data_variable.png) 156 | 157 | ## Setting up D3 Scales 158 | Since we are making a horizontal bar chart, we will utilize two scale functions: `scaleLinear` and `scaleBand`. `scaleLinear` creates a linear mapping while `scaleBand` is a mapping specific for bar charts. It will split the range into n (number of teams) bands and compute the positions and widths of the bands. 159 | ```javascript 160 | let y = d3.scaleBand() 161 | .domain(data.map(d => d.team).reverse()) 162 | .range([height, 0]) 163 | .padding(0.33) 164 | 165 | let x = d3.scaleLinear() 166 | .domain([0, Math.ceil(d3.max(data, d => d.value)/5)*5]) 167 | .range([0, width]) 168 | ``` 169 | ## Adding Axes 170 | We define our axis properties. Here it's the scale we want to use `x`, orientation `axisTop()` and approximately how many ticks it should display `ticks(6)`. We append another group element to the already defined `svg` variable using `.append("g")`, assign two classes `x axis` and then call the axis generator `xAxis` to draw it with the specified arguments. Similarly for the y-axis. 171 | ```javascript 172 | let xAxis = d3.axisTop(x) 173 | .ticks(6) 174 | 175 | svg.append("g") 176 | .attr("class", "x axis") 177 | .call(xAxis); 178 | 179 | let yAxis = d3.axisLeft(y) 180 | .tickFormat('') 181 | 182 | svg.append("g") 183 | .attr("class", "y axis") 184 | .call(yAxis); 185 | ``` 186 | ![create x-axis](img/create_x_axis.png) 187 | 188 | In addition to the axes, we want to add gridlines to the x-axis. Gridlines are coded very similarly to axes. 189 | ```javascript 190 | let gridlines = d3.axisTop(x) 191 | .ticks(6) 192 | .tickSize(-height) 193 | .tickFormat("") 194 | 195 | svg.append("g") 196 | .attr("class", "grid") 197 | .call(gridlines) 198 | ``` 199 | 200 | Let's add axes labels now. 201 | ```javascript 202 | labels = svg.append('g') 203 | .attr('class', 'label') 204 | 205 | labels.append('text') 206 | .attr('transform', `translate(${width},-40)`) 207 | .text('Wins') 208 | 209 | ylabel = labels.append('text') 210 | .attr('transform', `translate(-80,${height/2} rotate(-90)`) 211 | .text('Teams') 212 | ``` 213 | 214 | ## Individual Team Bar Charts 215 | Next, we will start displaying our data on the graph. Ultimately, we want to show the progression of total games won for each baseball game over a period of time. Each team will be represented by a bar, text, logo and a label. 216 | 217 | To set up the teams, we must first create groups to contain the collective information for each team. 218 | 219 | In D3, instead of telling D3 what to do, think of it as you are telling D3 what you want. The following piece of code constructs groups for each of the teams. 220 | ```javascript 221 | let bar = svg.selectAll(".bar") 222 | .data(data) 223 | .join("g") // equivalent to .enter().append('g') 224 | .attr("class", "bar") 225 | .attr("transform", d => `translate(0,${y(d.team)})`) 226 | ``` 227 | Here's a breakdown of the above code block: 228 | - `svg.selectAll(".bar)` says you want to select all element of type `class="bar"` (even if they don't exist at the beginning) 229 | - `.data(data)` binds the data to this empty D3 selection 230 | - `.join(g)` creates `g` elements for each row of data (i.e. team) 231 | 232 | Then for each `g` element: 233 | - `.attr('class', 'bar')` assigns `class="bar"` 234 | - `.attr("transform", d => 'translate(0,${y(d.team)})')` assigns a transformation (x,y) 235 | ![Create bar element](img/create_bar_element.png) 236 | 237 | **Note**: Data joins in D3 are probably one of the more harder concepts to grasp. Here is Mike Bostock's blog on [joins](https://bost.ocks.org/mike/join/) and [selections](https://bost.ocks.org/mike/selection/). 238 | 239 | Now we will add rectangles to each bar element and set the bar width corresponding to the wins for each respective team `.attr("width", d => x(d.value))`. 240 | We style the bar using `.style('fill', d => d3.interpolateRdYlBu(d.value/100))` which defines the number of games won by each team as a fraction between 0 and 1. We will add a color scheme to visually encode the number of wins (the bars will gradually change from red to yellow to blue as teams win more games). Its really not needed for the graph but I wanted to show you how to do it. 241 | ```javascript 242 | let rects = bar.append('rect') 243 | .attr("width", d => x(d.value)) 244 | .attr("height", y.bandwidth()) 245 | .style('fill', d => d3.interpolateRdYlBu(d.value/100)) 246 | ``` 247 | ![Create bar element](img/create_rect.png) 248 | 249 | More information on chromatic schemes can be found here: 250 | https://observablehq.com/@d3/color-schemes?collection=@d3/d3-scale-chromatic 251 | 252 | Let's add labels to identify each team. 253 | ```javascript 254 | bar.append('text') 255 | .attr('class', 'team') 256 | .attr('x', -10) 257 | .attr('y', y.bandwidth()/2 + 5) 258 | .text(d => d.team) 259 | ``` 260 | 261 | As well as logos for each team. 262 | ```javascript 263 | const imgsize = 40 264 | let imgs = bar.append("svg:image") 265 | .attr('class', 'logo') 266 | .attr('x', d => x(d.value) + 5) 267 | .attr('y', -5) 268 | .attr('width', imgsize) 269 | .attr('height', imgsize) 270 | .attr("xlink:href", d => `http://www.capsinfo.com/images/MLB_Team_Logos/${urls[d.team]}.png`) 271 | ``` 272 | 273 | And a label for the number of games the team has won. 274 | ```javascript 275 | let barLabels = bar.append('text') 276 | .attr('class', 'barlabel') 277 | .attr('x', d => x(d.value) + 10 + imgsize) 278 | .attr('y', y.bandwidth()/2 + 5) 279 | .text(d => d.value) 280 | ``` 281 | ![Added team, logo and games won labels](img/team_logo_games_labels.png) 282 | 283 | And lastly, we add the date to display the time frame. 284 | ```javascript 285 | const formatDate = d3.timeFormat('%b %-d, %Y') 286 | let dateLabel = labels.append('text') 287 | .attr('id', 'date') 288 | .attr('transform', `translate(0,-40)`) 289 | .text(formatDate(chartDate)) 290 | ``` 291 | 292 | ## Exercise #1 (Vertical Bar Chart) 293 | Lets try to apply what we've learned so far with an exercise. 294 | 295 | Go into the `exercise_1` folder and open up `exercise_1.js`. Change the url to `localhost:8000/exercise_1`. You should see a horizontal bar chart. 296 | ![Starting graph for exercise #1](img/exercise1.png) 297 | 298 | The goal of the exercise is to transform this horizontal bar chart into a vertical bar chart with the labels on the outside of the bars. 299 | ![Ending graph for exercise #1](img/exercise1_sol.png) 300 | 301 | To approach this, we can split it up into a couple steps: 302 | 1. Switching from a bar chart horiziontal to vertical is essentially changing the scaling of the axes. Try using `scaleBand` for x and `scaleLinear` for y and change the `range` appropriately. 303 | 304 | 2. We must switch the range of data in the `domain`. How should we do that? 305 | 306 | 3. We also have to consider how the rectangles were specified. What is the new `height` and `width`? What is the new `x` and `y`? 307 | 308 | 4. Position the bar labels accordingly. 309 | 310 | ## Animating the Graph 311 | Now that we have an idea of how the graph set up and plotting works, we will dive into animation. Going back to our inital example, the animation happens within HTML's `setInterval()` method. The `setInterval()` method calls a function at specified intervals (in our case, `T`). Our function will perform one transition every interval. 312 | 313 | For each transition, we need to do the following: 314 | - update the date 315 | - re-construct a new dataset up to current date 316 | - update the x-axis and gridlines 317 | - update the bar chart 318 | - sort the data and update the y-axis 319 | 320 | Here we set up the period, `T`, and assign a variable name to our setInterval method. The first thing we do is increment the date by one day and then update the `dateLabel` variable with new text. 321 | ```javascript 322 | const T = 300 323 | let dailyUpdate = setInterval(function() { 324 | chartDate = d3.timeDay.offset(chartDate,1) 325 | dateLabel.text(formatDate(chartDate)) 326 | // ... 327 | }, T); 328 | ``` 329 | 330 | We need to update our dataset with our new date. 331 | ```javascript 332 | data = filterData(chartDate) 333 | ``` 334 | 335 | We also need to update the graph's axes to make them responsive to the changing scores. We do this by updating the `x.domain` and then re-calling the `xAxis` and `gridlines` variables which are dependent on the variable `x`. 336 | 337 | For the x-axis, we are incrementing the scale by fives (arbitrary). D3 also has a `.nice()` method which you can add to let D3 choose a "nice" limit for you. 338 | ```javascript 339 | x.domain([0, Math.ceil(d3.max(data, d => d.value)/5)*5]); 340 | svg.select('.x.axis').transition().duration(T) 341 | .call(xAxis); 342 | svg.select('.grid').transition().duration(T) 343 | .call(gridlines); 344 | ``` 345 | 346 | Here we update each team's bar graph. We attach our updated dataset to `rects`. We then re-specify the `width` attribute and `fill` style. If we did just this, this would actually give it the effect of stop-motion animation. We add the `.transition().duration(T)` part to smooth the transition. Similarly, we do the same for the logos and the bar labels. For the logos, we just need to update the `x` attribute and for the labels, we need to update the `x, y, text` attributes. 347 | ```javascript 348 | rects.data(data) 349 | .transition().duration(T) 350 | .attr("width", d => x(d.value)) 351 | .style('fill', d => d3.interpolateRdYlBu(d.value/100)) 352 | 353 | imgs.data(data) 354 | .transition().duration(T) 355 | .attr('x', d => x(d.value) + 5) 356 | 357 | barLabels.data(data) 358 | .transition().duration(T) 359 | .attr('x', d => x(d.value) + 10 + imgsize) 360 | .attr('y', y.bandwidth()/2 + 5) 361 | .text(d => d.value) 362 | ``` 363 | 364 | For the y-axis, we need to update the `y.domain`. But we need to sort our new dataset first. We then update our `bar` variable by changing the `transform` attribute. 365 | ```javascript 366 | data.sort((a,b) => d3.descending(a.value,b.value)); 367 | y.domain(data.map(d => d.team).reverse()); 368 | bar.transition().duration(T) 369 | .attr("transform", d => `translate(0,${y(d.team)})`) 370 | ``` 371 | Recall that the `bar` variable points to a group of `g` elements where we have grouped a bunched of other elements together. This has the advantage of allowing us to make one call to move them all instead of multiple separate calls. These elements include the rectangle, team text, logo, and bar label. 372 | ![g element with 4 nested elements](img/g_element.png) 373 | 374 | Lastly, we have to define an `if` statement to check if its the end of the season so we can stop the forever loop using `clearInterval()` to clear the timer we set earlier with `setInterval()`. 375 | ```javascript 376 | if (chartDate > new Date(2018,9,1)) { 377 | clearInterval(dailyUpdate) 378 | } 379 | ``` 380 | 381 | ## Exercise #2 (Sort the Chart) 382 | We will start with the solution from Exercise #1. 383 | 384 | Go into folder `exercise_2` and open up `index.html` and `exercise_2.js`. 385 | 386 | Our goal is to add sorting to our graph. We want to be able to sort alphabetically and numerically with a click of a button. 387 | 388 | Sort alphabetically: 389 | ![Sorted alphabetically](img/alphabetically.png) 390 | 391 | Sort numerically: 392 | ![Sorted numerically](img/numerically.png) 393 | 394 | We will need to update both the HTML as well as the JavaScript. Here are some hints. 395 | 396 | Add this HTML snippet to the body of `index.html` to add two buttons 397 | ```html 398 |
399 | 403 |
404 |
405 | 409 |
410 | ``` 411 | *Hint*: Create the function `updateAlpha()`. The function should do 3 things: 412 | 1. Sort the data. To do a sort with D3, you would write something like this `data.sort((a,b) => d3.ascending(a.COLUMN, b.COLUMN))` 413 | where COLUMN is the name of your key or column 414 | 2. Define the new order of teams and call the axis generator again to update the graph's x-axis. 415 | ```javascript 416 | // I've started the solution for you. 417 | // You just need to finish it (ellipses indicate where) 418 | x.domain(...) 419 | svg.select(".xaxis") ... 420 | ``` 421 | 3. Reassign the values to update the height and the labels of the graph 422 | ```javascript 423 | bar.selectAll('rect') ... 424 | bar.selectAll('.barlabel') ... 425 | ``` 426 | If you can get this, then adding the other sort option should be more straightforward. If you get this working, try changing the dataset to see if it still works. 427 | 428 | ## Exercise #3 (Animated Sort) 429 | For our last exercise, we will animate the sorting in exercise #2. Recall, we just did some stop-motion animation in exercise #2 (albeit two frames). 430 | 431 | ![Alt Text](https://media.giphy.com/media/JTP0B9YicPKVuYMgXN/giphy.gif) 432 | 433 | Although this may sound hard, it is actually quite simple. All you have to do is add a `transition` to each moving part of the graph (rectangles, x-axis and bar labels) and define a time `duration` for the animation to occur. 434 | 435 | ### Easing 436 | If you get the `transition` working, try adding an easing function (e.g. `.ease(d3.easeBounce)`) to the transition. Eased transitions control the motion of the elements during a transition. Here are some examples of how to use it (v4). https://bl.ocks.org/d3noob/1ea51d03775b9650e8dfd03474e202fe 437 | 438 | ## Clipped Path 439 | Let's go over the code we've skipped so far. 440 | ```javascript 441 | d3.select('.chart').append("defs") 442 | .append("clipPath") 443 | .attr("id", "clip") 444 | .append("rect") 445 | .attr('x', 0) 446 | .attr('y', 0) 447 | .attr("width", width + margin.left + margin.right) 448 | .attr("height", 0.4*height) 449 | ``` 450 | 451 | This piece of D3 code creates the following html code snippet. 452 | ```html 453 | 454 | 455 | 456 | 457 | 458 | ``` 459 | 460 | If we inspect the `rect` element using inspector tool in the browser, we can see that it covers the top part of our bar chart. Its not currently drawn because of the `` tag which means that we just want to store the object and use it at a later time. Well now is the time. We can use this `rect` element to clip our chart to create a different effect. In our css file, we commented out one piece of code. 461 | ```css 462 | .chart { 463 | clip-path: url(#clip); 464 | } 465 | ``` 466 | 467 | This css code block wants to clip the `chart` class with an element that has `id="clip"` (our `clipPath` SVG element). Let's uncomment it and run the code again. See how we are getting the effect of teams entering and leaving the chart from the bottom. Nothing about our base chart has changed. We are just using some visual trickery to create this effect. 468 | 469 | ## References 470 | Mike Bostock's blog (creator of D3.js) 471 | https://bost.ocks.org/mike/ 472 | 473 | A beginner's tutorial to D3.js by Mike Bostock 474 | https://bost.ocks.org/mike/circles/ 475 | 476 | Gallery of D3.js examples 477 | https://bl.ocks.org/ 478 | 479 | Another gallery of simple D3.js examples 480 | https://www.d3-graph-gallery.com/index.html 481 | 482 | D3.js e-book to understand basics (they have books for v3, v4, and v5). It has line-by-line breakdown of code. 483 | https://leanpub.com/d3-t-and-t-v5 484 | 485 | Alex's sandbox of D3.js examples 486 | https://github.com/caocscar/d3js-examples 487 | -------------------------------------------------------------------------------- /mlb2018.csv: -------------------------------------------------------------------------------- 1 | date,team 2 | 20180329,ARI 3 | 20180329,ATL 4 | 20180329,SFN 5 | 20180329,CHN 6 | 20180329,NYN 7 | 20180329,MIL 8 | 20180329,BAL 9 | 20180329,CHA 10 | 20180329,OAK 11 | 20180329,SEA 12 | 20180329,TBA 13 | 20180329,HOU 14 | 20180329,NYA 15 | 20180330,ARI 16 | 20180330,PHI 17 | 20180330,WAS 18 | 20180330,SFN 19 | 20180330,MIA 20 | 20180330,MIL 21 | 20180330,PIT 22 | 20180330,ANA 23 | 20180330,BOS 24 | 20180330,TEX 25 | 20180330,NYA 26 | 20180331,COL 27 | 20180331,ATL 28 | 20180331,WAS 29 | 20180331,LAN 30 | 20180331,CHN 31 | 20180331,NYN 32 | 20180331,MIL 33 | 20180331,MIN 34 | 20180331,CHA 35 | 20180331,ANA 36 | 20180331,CLE 37 | 20180331,BOS 38 | 20180331,HOU 39 | 20180331,TOR 40 | 20180401,WAS 41 | 20180401,LAN 42 | 20180401,MIA 43 | 20180401,SLN 44 | 20180401,MIN 45 | 20180401,PIT 46 | 20180401,PIT 47 | 20180401,ANA 48 | 20180401,SEA 49 | 20180401,BOS 50 | 20180401,HOU 51 | 20180401,TOR 52 | 20180402,ARI 53 | 20180402,WAS 54 | 20180402,CIN 55 | 20180402,BOS 56 | 20180402,SLN 57 | 20180402,PIT 58 | 20180402,COL 59 | 20180402,CLE 60 | 20180402,DET 61 | 20180402,HOU 62 | 20180402,OAK 63 | 20180402,TOR 64 | 20180403,ARI 65 | 20180403,ATL 66 | 20180403,BOS 67 | 20180403,MIL 68 | 20180403,NYN 69 | 20180403,SDN 70 | 20180403,SEA 71 | 20180403,ANA 72 | 20180403,KCA 73 | 20180403,HOU 74 | 20180403,NYA 75 | 20180403,TEX 76 | 20180403,TOR 77 | 20180404,ARI 78 | 20180404,ATL 79 | 20180404,SLN 80 | 20180404,NYN 81 | 20180404,MIN 82 | 20180404,COL 83 | 20180404,SFN 84 | 20180404,ANA 85 | 20180404,HOU 86 | 20180404,NYA 87 | 20180404,OAK 88 | 20180404,CHA 89 | 20180405,CHN 90 | 20180405,PHI 91 | 20180405,PIT 92 | 20180405,COL 93 | 20180405,ARI 94 | 20180405,NYN 95 | 20180405,BOS 96 | 20180405,DET 97 | 20180405,MIN 98 | 20180405,BAL 99 | 20180405,TEX 100 | 20180406,ATL 101 | 20180406,MIL 102 | 20180406,PIT 103 | 20180406,ANA 104 | 20180406,CLE 105 | 20180406,SDN 106 | 20180406,BAL 107 | 20180406,TOR 108 | 20180407,COL 109 | 20180407,CHN 110 | 20180407,PHI 111 | 20180407,CIN 112 | 20180407,SFN 113 | 20180407,SLN 114 | 20180407,NYN 115 | 20180407,OAK 116 | 20180407,BOS 117 | 20180407,DET 118 | 20180407,KCA 119 | 20180407,HOU 120 | 20180407,SEA 121 | 20180407,NYA 122 | 20180407,TEX 123 | 20180408,ATL 124 | 20180408,CHN 125 | 20180408,MIA 126 | 20180408,PIT 127 | 20180408,LAN 128 | 20180408,ARI 129 | 20180408,NYN 130 | 20180408,ANA 131 | 20180408,BOS 132 | 20180408,DET 133 | 20180408,CLE 134 | 20180408,HOU 135 | 20180408,BAL 136 | 20180408,TOR 137 | 20180409,SDN 138 | 20180409,NYN 139 | 20180409,PHI 140 | 20180409,ARI 141 | 20180409,MIL 142 | 20180409,WAS 143 | 20180409,TOR 144 | 20180409,TBA 145 | 20180409,CLE 146 | 20180409,KCA 147 | 20180409,HOU 148 | 20180409,ANA 149 | 20180410,PIT 150 | 20180410,SDN 151 | 20180410,LAN 152 | 20180410,NYN 153 | 20180410,PHI 154 | 20180410,SFN 155 | 20180410,SLN 156 | 20180410,WAS 157 | 20180410,TOR 158 | 20180410,BOS 159 | 20180410,TBA 160 | 20180410,CLE 161 | 20180410,SEA 162 | 20180410,MIN 163 | 20180410,ANA 164 | 20180411,CHN 165 | 20180411,COL 166 | 20180411,OAK 167 | 20180411,NYN 168 | 20180411,PHI 169 | 20180411,ARI 170 | 20180411,MIL 171 | 20180411,ATL 172 | 20180411,BAL 173 | 20180411,NYA 174 | 20180411,CHA 175 | 20180411,CLE 176 | 20180411,SEA 177 | 20180411,MIN 178 | 20180411,ANA 179 | 20180412,PIT 180 | 20180412,SLN 181 | 20180412,SFN 182 | 20180412,COL 183 | 20180412,BOS 184 | 20180412,CLE 185 | 20180412,ANA 186 | 20180412,MIN 187 | 20180413,ATL 188 | 20180413,SLN 189 | 20180413,ARI 190 | 20180413,MIA 191 | 20180413,NYN 192 | 20180413,SDN 193 | 20180413,COL 194 | 20180413,BOS 195 | 20180413,TOR 196 | 20180413,NYA 197 | 20180413,HOU 198 | 20180413,ANA 199 | 20180413,SEA 200 | 20180413,PHI 201 | 20180414,CHN 202 | 20180414,SLN 203 | 20180414,ARI 204 | 20180414,PIT 205 | 20180414,MIL 206 | 20180414,SDN 207 | 20180414,WAS 208 | 20180414,BOS 209 | 20180414,TEX 210 | 20180414,ANA 211 | 20180414,SEA 212 | 20180414,PHI 213 | 20180415,SLN 214 | 20180415,LAN 215 | 20180415,PIT 216 | 20180415,NYN 217 | 20180415,SDN 218 | 20180415,COL 219 | 20180415,BOS 220 | 20180415,TEX 221 | 20180415,OAK 222 | 20180415,PHI 223 | 20180416,ATL 224 | 20180416,CIN 225 | 20180416,WAS 226 | 20180416,COL 227 | 20180416,LAN 228 | 20180416,NYA 229 | 20180416,OAK 230 | 20180416,SEA 231 | 20180416,TBA 232 | 20180417,ARI 233 | 20180417,PHI 234 | 20180417,SLN 235 | 20180417,MIL 236 | 20180417,WAS 237 | 20180417,COL 238 | 20180417,LAN 239 | 20180417,BOS 240 | 20180417,DET 241 | 20180417,CLE 242 | 20180417,MIA 243 | 20180417,OAK 244 | 20180417,HOU 245 | 20180417,TEX 246 | 20180417,TOR 247 | 20180417,TOR 248 | 20180418,SFN 249 | 20180418,ATL 250 | 20180418,MIL 251 | 20180418,NYN 252 | 20180418,PIT 253 | 20180418,LAN 254 | 20180418,BOS 255 | 20180418,DET 256 | 20180418,MIN 257 | 20180418,OAK 258 | 20180418,HOU 259 | 20180418,TBA 260 | 20180418,TOR 261 | 20180419,ARI 262 | 20180419,ATL 263 | 20180419,CHN 264 | 20180419,MIL 265 | 20180419,PHI 266 | 20180419,BOS 267 | 20180419,DET 268 | 20180419,NYA 269 | 20180419,HOU 270 | 20180420,SDN 271 | 20180420,NYN 272 | 20180420,CHN 273 | 20180420,WAS 274 | 20180420,MIL 275 | 20180420,PHI 276 | 20180420,SLN 277 | 20180420,SFN 278 | 20180420,BAL 279 | 20180420,HOU 280 | 20180420,DET 281 | 20180420,KCA 282 | 20180420,TOR 283 | 20180420,BOS 284 | 20180420,TBA 285 | 20180420,SEA 286 | 20180421,ARI 287 | 20180421,ATL 288 | 20180421,COL 289 | 20180421,LAN 290 | 20180421,MIL 291 | 20180421,PHI 292 | 20180421,SLN 293 | 20180421,ANA 294 | 20180421,CLE 295 | 20180421,HOU 296 | 20180421,DET 297 | 20180421,NYA 298 | 20180421,OAK 299 | 20180421,TBA 300 | 20180421,SEA 301 | 20180422,ARI 302 | 20180422,CHN 303 | 20180422,LAN 304 | 20180422,MIL 305 | 20180422,PHI 306 | 20180422,SLN 307 | 20180422,SFN 308 | 20180422,CLE 309 | 20180422,HOU 310 | 20180422,KCA 311 | 20180422,NYA 312 | 20180422,OAK 313 | 20180422,TBA 314 | 20180422,TEX 315 | 20180423,CIN 316 | 20180423,SDN 317 | 20180423,LAN 318 | 20180423,SFN 319 | 20180423,CLE 320 | 20180423,CHA 321 | 20180423,ANA 322 | 20180423,NYA 323 | 20180423,OAK 324 | 20180424,CIN 325 | 20180424,COL 326 | 20180424,MIA 327 | 20180424,ARI 328 | 20180424,SFN 329 | 20180424,NYN 330 | 20180424,SEA 331 | 20180424,CHN 332 | 20180424,ANA 333 | 20180424,MIL 334 | 20180424,NYA 335 | 20180424,OAK 336 | 20180424,TOR 337 | 20180425,ATL 338 | 20180425,COL 339 | 20180425,MIA 340 | 20180425,PHI 341 | 20180425,DET 342 | 20180425,PIT 343 | 20180425,WAS 344 | 20180425,SLN 345 | 20180425,TBA 346 | 20180425,SEA 347 | 20180425,CLE 348 | 20180425,HOU 349 | 20180425,MIL 350 | 20180425,NYA 351 | 20180425,TEX 352 | 20180425,BOS 353 | 20180426,CHN 354 | 20180426,ATL 355 | 20180426,ARI 356 | 20180426,PIT 357 | 20180426,SLN 358 | 20180426,TBA 359 | 20180426,SEA 360 | 20180426,CHA 361 | 20180426,NYA 362 | 20180426,BOS 363 | 20180427,CHN 364 | 20180427,COL 365 | 20180427,PHI 366 | 20180427,PIT 367 | 20180427,NYN 368 | 20180427,SFN 369 | 20180427,ARI 370 | 20180427,NYA 371 | 20180427,BAL 372 | 20180427,TBA 373 | 20180427,CLE 374 | 20180427,OAK 375 | 20180427,CHA 376 | 20180427,CIN 377 | 20180427,TEX 378 | 20180428,CHN 379 | 20180428,MIA 380 | 20180428,ATL 381 | 20180428,PIT 382 | 20180428,SDN 383 | 20180428,LAN 384 | 20180428,SFN 385 | 20180428,ARI 386 | 20180428,NYA 387 | 20180428,DET 388 | 20180428,TBA 389 | 20180428,SEA 390 | 20180428,HOU 391 | 20180428,CHA 392 | 20180428,KCA 393 | 20180428,MIN 394 | 20180428,TEX 395 | 20180429,CHN 396 | 20180429,MIA 397 | 20180429,ATL 398 | 20180429,PIT 399 | 20180429,NYN 400 | 20180429,SFN 401 | 20180429,WAS 402 | 20180429,NYA 403 | 20180429,BAL 404 | 20180429,BOS 405 | 20180429,SEA 406 | 20180429,HOU 407 | 20180429,KCA 408 | 20180429,CIN 409 | 20180429,TOR 410 | 20180430,ARI 411 | 20180430,CHN 412 | 20180430,MIL 413 | 20180430,MIA 414 | 20180430,SFN 415 | 20180430,WAS 416 | 20180430,BOS 417 | 20180430,CLE 418 | 20180430,TBA 419 | 20180430,HOU 420 | 20180430,TOR 421 | 20180501,ARI 422 | 20180501,COL 423 | 20180501,MIL 424 | 20180501,MIA 425 | 20180501,ATL 426 | 20180501,SDN 427 | 20180501,SLN 428 | 20180501,WAS 429 | 20180501,ANA 430 | 20180501,KCA 431 | 20180501,TEX 432 | 20180501,DET 433 | 20180501,NYA 434 | 20180501,TOR 435 | 20180501,SEA 436 | 20180502,LAN 437 | 20180502,COL 438 | 20180502,MIL 439 | 20180502,PHI 440 | 20180502,ATL 441 | 20180502,SFN 442 | 20180502,SLN 443 | 20180502,WAS 444 | 20180502,ANA 445 | 20180502,BOS 446 | 20180502,CLE 447 | 20180502,DET 448 | 20180502,NYA 449 | 20180502,MIN 450 | 20180502,OAK 451 | 20180503,LAN 452 | 20180503,ATL 453 | 20180503,WAS 454 | 20180503,ANA 455 | 20180503,CHA 456 | 20180503,TOR 457 | 20180503,CLE 458 | 20180503,NYA 459 | 20180503,KCA 460 | 20180503,SEA 461 | 20180503,TEX 462 | 20180504,HOU 463 | 20180504,SFN 464 | 20180504,CIN 465 | 20180504,PIT 466 | 20180504,COL 467 | 20180504,LAN 468 | 20180504,SLN 469 | 20180504,WAS 470 | 20180504,MIN 471 | 20180504,KCA 472 | 20180504,NYA 473 | 20180504,OAK 474 | 20180504,ANA 475 | 20180504,TBA 476 | 20180504,BOS 477 | 20180505,ARI 478 | 20180505,SFN 479 | 20180505,MIA 480 | 20180505,MIL 481 | 20180505,COL 482 | 20180505,SDN 483 | 20180505,SLN 484 | 20180505,PHI 485 | 20180505,MIN 486 | 20180505,DET 487 | 20180505,NYA 488 | 20180505,OAK 489 | 20180505,SEA 490 | 20180505,TBA 491 | 20180505,BOS 492 | 20180506,ARI 493 | 20180506,SFN 494 | 20180506,MIA 495 | 20180506,PIT 496 | 20180506,COL 497 | 20180506,SDN 498 | 20180506,SLN 499 | 20180506,WAS 500 | 20180506,MIN 501 | 20180506,KCA 502 | 20180506,NYA 503 | 20180506,OAK 504 | 20180506,ANA 505 | 20180506,TOR 506 | 20180506,BOS 507 | 20180507,CHN 508 | 20180507,NYN 509 | 20180507,PHI 510 | 20180507,WAS 511 | 20180507,MIN 512 | 20180507,HOU 513 | 20180507,TEX 514 | 20180508,CHN 515 | 20180508,CIN 516 | 20180508,COL 517 | 20180508,ARI 518 | 20180508,MIL 519 | 20180508,PHI 520 | 20180508,WAS 521 | 20180508,MIN 522 | 20180508,KCA 523 | 20180508,PIT 524 | 20180508,NYA 525 | 20180508,HOU 526 | 20180508,ATL 527 | 20180508,DET 528 | 20180508,SEA 529 | 20180509,CHN 530 | 20180509,CIN 531 | 20180509,ANA 532 | 20180509,LAN 533 | 20180509,CLE 534 | 20180509,PHI 535 | 20180509,SDN 536 | 20180509,BAL 537 | 20180509,PIT 538 | 20180509,NYA 539 | 20180509,HOU 540 | 20180509,ATL 541 | 20180509,TEX 542 | 20180509,TOR 543 | 20180510,WAS 544 | 20180510,MIL 545 | 20180510,CIN 546 | 20180510,ATL 547 | 20180510,PHI 548 | 20180510,SLN 549 | 20180510,ANA 550 | 20180510,BAL 551 | 20180510,BOS 552 | 20180510,SEA 553 | 20180511,WAS 554 | 20180511,CHN 555 | 20180511,MIL 556 | 20180511,CIN 557 | 20180511,MIA 558 | 20180511,NYN 559 | 20180511,PIT 560 | 20180511,SLN 561 | 20180511,MIN 562 | 20180511,BAL 563 | 20180511,KCA 564 | 20180511,TEX 565 | 20180511,OAK 566 | 20180511,TOR 567 | 20180512,WAS 568 | 20180512,CHN 569 | 20180512,COL 570 | 20180512,CIN 571 | 20180512,ATL 572 | 20180512,PIT 573 | 20180512,SDN 574 | 20180512,MIN 575 | 20180512,BAL 576 | 20180512,TBA 577 | 20180512,CLE 578 | 20180512,DET 579 | 20180512,SEA 580 | 20180512,HOU 581 | 20180512,NYA 582 | 20180512,BOS 583 | 20180513,WAS 584 | 20180513,CHA 585 | 20180513,MIL 586 | 20180513,CIN 587 | 20180513,ATL 588 | 20180513,PHI 589 | 20180513,SFN 590 | 20180513,SDN 591 | 20180513,ANA 592 | 20180513,BAL 593 | 20180513,CLE 594 | 20180513,DET 595 | 20180513,HOU 596 | 20180513,NYA 597 | 20180513,BOS 598 | 20180514,MIL 599 | 20180514,ATL 600 | 20180514,COL 601 | 20180514,SFN 602 | 20180514,ANA 603 | 20180514,OAK 604 | 20180514,DET 605 | 20180514,TBA 606 | 20180514,SEA 607 | 20180515,ARI 608 | 20180515,CHN 609 | 20180515,MIA 610 | 20180515,NYN 611 | 20180515,PIT 612 | 20180515,SDN 613 | 20180515,SFN 614 | 20180515,WAS 615 | 20180515,HOU 616 | 20180515,OAK 617 | 20180515,DET 618 | 20180515,TBA 619 | 20180515,MIN 620 | 20180515,SEA 621 | 20180516,MIL 622 | 20180516,ATL 623 | 20180516,MIA 624 | 20180516,TOR 625 | 20180516,PIT 626 | 20180516,CIN 627 | 20180516,HOU 628 | 20180516,PHI 629 | 20180516,BOS 630 | 20180516,CLE 631 | 20180516,TBA 632 | 20180516,SLN 633 | 20180516,TEX 634 | 20180517,LAN 635 | 20180517,PIT 636 | 20180517,COL 637 | 20180517,PHI 638 | 20180517,TBA 639 | 20180517,BOS 640 | 20180517,CHA 641 | 20180517,DET 642 | 20180517,OAK 643 | 20180518,MIA 644 | 20180518,CHN 645 | 20180518,NYN 646 | 20180518,SDN 647 | 20180518,COL 648 | 20180518,SLN 649 | 20180518,TBA 650 | 20180518,BAL 651 | 20180518,TEX 652 | 20180518,HOU 653 | 20180518,KCA 654 | 20180518,MIL 655 | 20180518,SEA 656 | 20180518,OAK 657 | 20180519,ATL 658 | 20180519,CIN 659 | 20180519,CHN 660 | 20180519,NYN 661 | 20180519,SDN 662 | 20180519,SFN 663 | 20180519,PHI 664 | 20180519,LAN 665 | 20180519,LAN 666 | 20180519,TBA 667 | 20180519,BOS 668 | 20180519,CHA 669 | 20180519,CLE 670 | 20180519,NYA 671 | 20180519,MIL 672 | 20180519,SEA 673 | 20180519,OAK 674 | 20180520,ATL 675 | 20180520,CHN 676 | 20180520,NYN 677 | 20180520,SDN 678 | 20180520,SFN 679 | 20180520,SLN 680 | 20180520,LAN 681 | 20180520,ANA 682 | 20180520,BOS 683 | 20180520,CHA 684 | 20180520,HOU 685 | 20180520,NYA 686 | 20180520,MIN 687 | 20180520,SEA 688 | 20180520,OAK 689 | 20180521,COL 690 | 20180521,MIL 691 | 20180521,NYN 692 | 20180521,PHI 693 | 20180521,SLN 694 | 20180521,WAS 695 | 20180521,BAL 696 | 20180521,MIN 697 | 20180521,NYA 698 | 20180522,CLE 699 | 20180522,CIN 700 | 20180522,LAN 701 | 20180522,MIL 702 | 20180522,MIA 703 | 20180522,ATL 704 | 20180522,KCA 705 | 20180522,WAS 706 | 20180522,CHA 707 | 20180522,HOU 708 | 20180522,MIN 709 | 20180522,SEA 710 | 20180522,BOS 711 | 20180522,TEX 712 | 20180522,TOR 713 | 20180523,CLE 714 | 20180523,PIT 715 | 20180523,LAN 716 | 20180523,MIL 717 | 20180523,MIA 718 | 20180523,PHI 719 | 20180523,KCA 720 | 20180523,SDN 721 | 20180523,CHA 722 | 20180523,HOU 723 | 20180523,DET 724 | 20180523,SEA 725 | 20180523,BOS 726 | 20180523,TEX 727 | 20180523,ANA 728 | 20180524,CIN 729 | 20180524,NYN 730 | 20180524,BAL 731 | 20180524,HOU 732 | 20180524,OAK 733 | 20180524,TBA 734 | 20180524,KCA 735 | 20180524,ANA 736 | 20180525,CHN 737 | 20180525,COL 738 | 20180525,LAN 739 | 20180525,WAS 740 | 20180525,MIL 741 | 20180525,TOR 742 | 20180525,PIT 743 | 20180525,BOS 744 | 20180525,HOU 745 | 20180525,DET 746 | 20180525,NYA 747 | 20180525,ARI 748 | 20180525,SEA 749 | 20180525,BAL 750 | 20180525,TEX 751 | 20180526,SFN 752 | 20180526,CIN 753 | 20180526,SDN 754 | 20180526,WAS 755 | 20180526,MIL 756 | 20180526,PHI 757 | 20180526,SLN 758 | 20180526,BOS 759 | 20180526,CLE 760 | 20180526,CHA 761 | 20180526,ANA 762 | 20180526,OAK 763 | 20180526,SEA 764 | 20180526,TBA 765 | 20180526,TEX 766 | 20180527,CHN 767 | 20180527,COL 768 | 20180527,LAN 769 | 20180527,WAS 770 | 20180527,MIL 771 | 20180527,TOR 772 | 20180527,SLN 773 | 20180527,ATL 774 | 20180527,CLE 775 | 20180527,DET 776 | 20180527,NYA 777 | 20180527,OAK 778 | 20180527,SEA 779 | 20180527,TBA 780 | 20180527,KCA 781 | 20180528,ARI 782 | 20180528,ATL 783 | 20180528,NYN 784 | 20180528,COL 785 | 20180528,LAN 786 | 20180528,MIL 787 | 20180528,CHN 788 | 20180528,MIA 789 | 20180528,WAS 790 | 20180528,BOS 791 | 20180528,CLE 792 | 20180528,DET 793 | 20180528,MIN 794 | 20180528,HOU 795 | 20180528,TBA 796 | 20180528,SEA 797 | 20180529,ARI 798 | 20180529,ATL 799 | 20180529,COL 800 | 20180529,PHI 801 | 20180529,SLN 802 | 20180529,CHN 803 | 20180529,SDN 804 | 20180529,WAS 805 | 20180529,BOS 806 | 20180529,CLE 807 | 20180529,ANA 808 | 20180529,KCA 809 | 20180529,NYA 810 | 20180529,TBA 811 | 20180529,TEX 812 | 20180530,CIN 813 | 20180530,NYN 814 | 20180530,SFN 815 | 20180530,LAN 816 | 20180530,MIL 817 | 20180530,PIT 818 | 20180530,SDN 819 | 20180530,WAS 820 | 20180530,BOS 821 | 20180530,CLE 822 | 20180530,DET 823 | 20180530,KCA 824 | 20180530,NYA 825 | 20180530,TBA 826 | 20180530,TEX 827 | 20180531,ATL 828 | 20180531,PHI 829 | 20180531,CHN 830 | 20180531,SDN 831 | 20180531,SLN 832 | 20180531,DET 833 | 20180531,HOU 834 | 20180531,CLE 835 | 20180531,OAK 836 | 20180531,SEA 837 | 20180601,ARI 838 | 20180601,ATL 839 | 20180601,LAN 840 | 20180601,CHN 841 | 20180601,CIN 842 | 20180601,SFN 843 | 20180601,PIT 844 | 20180601,ANA 845 | 20180601,NYA 846 | 20180601,CHA 847 | 20180601,DET 848 | 20180601,HOU 849 | 20180601,OAK 850 | 20180601,MIN 851 | 20180601,SEA 852 | 20180602,ARI 853 | 20180602,WAS 854 | 20180602,LAN 855 | 20180602,CHN 856 | 20180602,SDN 857 | 20180602,SFN 858 | 20180602,SLN 859 | 20180602,TEX 860 | 20180602,NYA 861 | 20180602,MIL 862 | 20180602,DET 863 | 20180602,BOS 864 | 20180602,KCA 865 | 20180602,MIN 866 | 20180602,SEA 867 | 20180603,ARI 868 | 20180603,ATL 869 | 20180603,LAN 870 | 20180603,CHN 871 | 20180603,SDN 872 | 20180603,SFN 873 | 20180603,SLN 874 | 20180603,ANA 875 | 20180603,CHA 876 | 20180603,TOR 877 | 20180603,BOS 878 | 20180603,OAK 879 | 20180603,MIN 880 | 20180603,SEA 881 | 20180604,SDN 882 | 20180604,SFN 883 | 20180604,ANA 884 | 20180604,NYA 885 | 20180604,DET 886 | 20180605,PHI 887 | 20180605,COL 888 | 20180605,BAL 889 | 20180605,LAN 890 | 20180605,ATL 891 | 20180605,ARI 892 | 20180605,MIA 893 | 20180605,WAS 894 | 20180605,ANA 895 | 20180605,BOS 896 | 20180605,CLE 897 | 20180605,SEA 898 | 20180605,MIN 899 | 20180605,CHA 900 | 20180605,TEX 901 | 20180605,NYA 902 | 20180606,CHN 903 | 20180606,COL 904 | 20180606,BAL 905 | 20180606,PIT 906 | 20180606,SDN 907 | 20180606,SFN 908 | 20180606,MIA 909 | 20180606,WAS 910 | 20180606,ANA 911 | 20180606,BOS 912 | 20180606,CLE 913 | 20180606,HOU 914 | 20180606,CHA 915 | 20180606,TEX 916 | 20180606,NYA 917 | 20180607,CHN 918 | 20180607,CIN 919 | 20180607,LAN 920 | 20180607,SLN 921 | 20180607,DET 922 | 20180607,MIN 923 | 20180607,OAK 924 | 20180607,SEA 925 | 20180607,HOU 926 | 20180607,TOR 927 | 20180608,CHN 928 | 20180608,SLN 929 | 20180608,ARI 930 | 20180608,LAN 931 | 20180608,MIA 932 | 20180608,NYA 933 | 20180608,MIL 934 | 20180608,SFN 935 | 20180608,CHA 936 | 20180608,CLE 937 | 20180608,ANA 938 | 20180608,OAK 939 | 20180608,SEA 940 | 20180608,HOU 941 | 20180608,TOR 942 | 20180609,CHN 943 | 20180609,SLN 944 | 20180609,ARI 945 | 20180609,ATL 946 | 20180609,SDN 947 | 20180609,NYA 948 | 20180609,MIL 949 | 20180609,WAS 950 | 20180609,BOS 951 | 20180609,DET 952 | 20180609,ANA 953 | 20180609,KCA 954 | 20180609,TBA 955 | 20180609,HOU 956 | 20180609,TOR 957 | 20180610,PIT 958 | 20180610,CIN 959 | 20180610,ARI 960 | 20180610,LAN 961 | 20180610,SDN 962 | 20180610,NYN 963 | 20180610,PHI 964 | 20180610,SFN 965 | 20180610,CHA 966 | 20180610,CLE 967 | 20180610,MIN 968 | 20180610,OAK 969 | 20180610,SEA 970 | 20180610,HOU 971 | 20180610,TOR 972 | 20180611,ARI 973 | 20180611,MIA 974 | 20180611,CHN 975 | 20180611,SLN 976 | 20180611,BOS 977 | 20180611,CLE 978 | 20180611,SEA 979 | 20180611,TBA 980 | 20180612,ARI 981 | 20180612,ATL 982 | 20180612,LAN 983 | 20180612,MIA 984 | 20180612,MIL 985 | 20180612,PHI 986 | 20180612,SDN 987 | 20180612,BOS 988 | 20180612,CHA 989 | 20180612,MIN 990 | 20180612,CIN 991 | 20180612,NYA 992 | 20180612,HOU 993 | 20180612,SEA 994 | 20180612,TBA 995 | 20180613,PIT 996 | 20180613,ATL 997 | 20180613,LAN 998 | 20180613,MIA 999 | 20180613,MIL 1000 | 20180613,COL 1001 | 20180613,SDN 1002 | 20180613,BOS 1003 | 20180613,CHA 1004 | 20180613,DET 1005 | 20180613,CIN 1006 | 20180613,WAS 1007 | 20180613,HOU 1008 | 20180613,SEA 1009 | 20180613,TBA 1010 | 20180614,ARI 1011 | 20180614,ATL 1012 | 20180614,SFN 1013 | 20180614,PHI 1014 | 20180614,CLE 1015 | 20180614,DET 1016 | 20180614,NYA 1017 | 20180614,HOU 1018 | 20180614,BOS 1019 | 20180615,ARI 1020 | 20180615,SDN 1021 | 20180615,LAN 1022 | 20180615,MIL 1023 | 20180615,PIT 1024 | 20180615,CHN 1025 | 20180615,MIA 1026 | 20180615,DET 1027 | 20180615,MIN 1028 | 20180615,HOU 1029 | 20180615,NYA 1030 | 20180615,ANA 1031 | 20180615,SEA 1032 | 20180615,COL 1033 | 20180615,TOR 1034 | 20180616,NYN 1035 | 20180616,ATL 1036 | 20180616,LAN 1037 | 20180616,PHI 1038 | 20180616,PIT 1039 | 20180616,CHN 1040 | 20180616,MIA 1041 | 20180616,DET 1042 | 20180616,MIN 1043 | 20180616,HOU 1044 | 20180616,NYA 1045 | 20180616,OAK 1046 | 20180616,SEA 1047 | 20180616,TEX 1048 | 20180616,TOR 1049 | 20180617,NYN 1050 | 20180617,ATL 1051 | 20180617,SFN 1052 | 20180617,PHI 1053 | 20180617,CIN 1054 | 20180617,SLN 1055 | 20180617,BAL 1056 | 20180617,DET 1057 | 20180617,CLE 1058 | 20180617,HOU 1059 | 20180617,TBA 1060 | 20180617,OAK 1061 | 20180617,BOS 1062 | 20180617,TEX 1063 | 20180617,TOR 1064 | 20180618,NYN 1065 | 20180618,PHI 1066 | 20180618,PIT 1067 | 20180618,MIA 1068 | 20180618,NYA 1069 | 20180618,ARI 1070 | 20180618,CLE 1071 | 20180618,HOU 1072 | 20180618,TEX 1073 | 20180619,LAN 1074 | 20180619,CHN 1075 | 20180619,CIN 1076 | 20180619,COL 1077 | 20180619,SLN 1078 | 20180619,MIL 1079 | 20180619,OAK 1080 | 20180619,SFN 1081 | 20180619,WAS 1082 | 20180619,ANA 1083 | 20180619,CLE 1084 | 20180619,TBA 1085 | 20180619,TEX 1086 | 20180619,MIN 1087 | 20180619,NYA 1088 | 20180619,ATL 1089 | 20180620,CHN 1090 | 20180620,CIN 1091 | 20180620,COL 1092 | 20180620,PHI 1093 | 20180620,OAK 1094 | 20180620,SFN 1095 | 20180620,BAL 1096 | 20180620,CLE 1097 | 20180620,HOU 1098 | 20180620,TEX 1099 | 20180620,MIN 1100 | 20180620,NYA 1101 | 20180620,TOR 1102 | 20180621,CIN 1103 | 20180621,COL 1104 | 20180621,MIL 1105 | 20180621,ARI 1106 | 20180621,SFN 1107 | 20180621,WAS 1108 | 20180621,ANA 1109 | 20180621,BOS 1110 | 20180621,NYA 1111 | 20180622,BAL 1112 | 20180622,CIN 1113 | 20180622,COL 1114 | 20180622,MIL 1115 | 20180622,LAN 1116 | 20180622,ARI 1117 | 20180622,SDN 1118 | 20180622,PHI 1119 | 20180622,ANA 1120 | 20180622,BOS 1121 | 20180622,OAK 1122 | 20180622,CHA 1123 | 20180622,CLE 1124 | 20180622,KCA 1125 | 20180622,TEX 1126 | 20180622,TBA 1127 | 20180623,BAL 1128 | 20180623,CIN 1129 | 20180623,MIA 1130 | 20180623,SLN 1131 | 20180623,LAN 1132 | 20180623,ARI 1133 | 20180623,SFN 1134 | 20180623,PHI 1135 | 20180623,TOR 1136 | 20180623,SEA 1137 | 20180623,OAK 1138 | 20180623,CLE 1139 | 20180623,HOU 1140 | 20180623,TEX 1141 | 20180623,TBA 1142 | 20180624,ATL 1143 | 20180624,CIN 1144 | 20180624,MIA 1145 | 20180624,SLN 1146 | 20180624,LAN 1147 | 20180624,ARI 1148 | 20180624,SFN 1149 | 20180624,WAS 1150 | 20180624,TOR 1151 | 20180624,BOS 1152 | 20180624,CHA 1153 | 20180624,CLE 1154 | 20180624,HOU 1155 | 20180624,MIN 1156 | 20180624,TBA 1157 | 20180625,ATL 1158 | 20180625,LAN 1159 | 20180625,MIA 1160 | 20180625,PIT 1161 | 20180625,NYA 1162 | 20180625,SLN 1163 | 20180625,SEA 1164 | 20180625,OAK 1165 | 20180625,TOR 1166 | 20180625,KCA 1167 | 20180625,TBA 1168 | 20180625,TEX 1169 | 20180626,CIN 1170 | 20180626,CHN 1171 | 20180626,ARI 1172 | 20180626,MIL 1173 | 20180626,NYN 1174 | 20180626,NYA 1175 | 20180626,SFN 1176 | 20180626,SLN 1177 | 20180626,SEA 1178 | 20180626,BOS 1179 | 20180626,CHA 1180 | 20180626,OAK 1181 | 20180626,HOU 1182 | 20180626,TBA 1183 | 20180626,SDN 1184 | 20180627,CIN 1185 | 20180627,LAN 1186 | 20180627,ARI 1187 | 20180627,KCA 1188 | 20180627,PIT 1189 | 20180627,PHI 1190 | 20180627,SFN 1191 | 20180627,CLE 1192 | 20180627,SEA 1193 | 20180627,BOS 1194 | 20180627,CHA 1195 | 20180627,OAK 1196 | 20180627,HOU 1197 | 20180627,TEX 1198 | 20180628,MIL 1199 | 20180628,CHN 1200 | 20180628,ARI 1201 | 20180628,PHI 1202 | 20180628,COL 1203 | 20180628,SEA 1204 | 20180628,BOS 1205 | 20180628,MIN 1206 | 20180628,OAK 1207 | 20180628,HOU 1208 | 20180629,SFN 1209 | 20180629,CHN 1210 | 20180629,MIL 1211 | 20180629,COL 1212 | 20180629,MIA 1213 | 20180629,WAS 1214 | 20180629,PIT 1215 | 20180629,ATL 1216 | 20180629,ANA 1217 | 20180629,NYA 1218 | 20180629,OAK 1219 | 20180629,SEA 1220 | 20180629,TBA 1221 | 20180629,TEX 1222 | 20180629,TOR 1223 | 20180630,SFN 1224 | 20180630,CHN 1225 | 20180630,CIN 1226 | 20180630,COL 1227 | 20180630,MIA 1228 | 20180630,PHI 1229 | 20180630,SDN 1230 | 20180630,ATL 1231 | 20180630,ANA 1232 | 20180630,BOS 1233 | 20180630,OAK 1234 | 20180630,SEA 1235 | 20180630,TBA 1236 | 20180630,TEX 1237 | 20180630,TOR 1238 | 20180701,SFN 1239 | 20180701,CHN 1240 | 20180701,CIN 1241 | 20180701,LAN 1242 | 20180701,NYN 1243 | 20180701,PHI 1244 | 20180701,PIT 1245 | 20180701,ATL 1246 | 20180701,BAL 1247 | 20180701,NYA 1248 | 20180701,CLE 1249 | 20180701,SEA 1250 | 20180701,TBA 1251 | 20180701,CHA 1252 | 20180701,DET 1253 | 20180702,SLN 1254 | 20180702,CIN 1255 | 20180702,COL 1256 | 20180702,LAN 1257 | 20180702,MIA 1258 | 20180702,MIL 1259 | 20180702,BOS 1260 | 20180702,CLE 1261 | 20180702,ATL 1262 | 20180702,DET 1263 | 20180703,ARI 1264 | 20180703,CHN 1265 | 20180703,CHA 1266 | 20180703,COL 1267 | 20180703,LAN 1268 | 20180703,TBA 1269 | 20180703,MIL 1270 | 20180703,PHI 1271 | 20180703,BOS 1272 | 20180703,CLE 1273 | 20180703,NYA 1274 | 20180703,OAK 1275 | 20180703,SEA 1276 | 20180703,HOU 1277 | 20180703,TOR 1278 | 20180704,SLN 1279 | 20180704,CHN 1280 | 20180704,CIN 1281 | 20180704,COL 1282 | 20180704,LAN 1283 | 20180704,MIA 1284 | 20180704,MIL 1285 | 20180704,PHI 1286 | 20180704,BOS 1287 | 20180704,CLE 1288 | 20180704,NYA 1289 | 20180704,OAK 1290 | 20180704,ANA 1291 | 20180704,HOU 1292 | 20180704,NYN 1293 | 20180705,SDN 1294 | 20180705,MIL 1295 | 20180705,SLN 1296 | 20180705,WAS 1297 | 20180705,TEX 1298 | 20180705,HOU 1299 | 20180705,MIN 1300 | 20180705,SEA 1301 | 20180706,ARI 1302 | 20180706,CIN 1303 | 20180706,MIL 1304 | 20180706,NYN 1305 | 20180706,PHI 1306 | 20180706,SFN 1307 | 20180706,WAS 1308 | 20180706,ANA 1309 | 20180706,CLE 1310 | 20180706,DET 1311 | 20180706,HOU 1312 | 20180706,BOS 1313 | 20180706,MIN 1314 | 20180706,COL 1315 | 20180706,TOR 1316 | 20180707,ARI 1317 | 20180707,CHN 1318 | 20180707,ATL 1319 | 20180707,TBA 1320 | 20180707,PHI 1321 | 20180707,SLN 1322 | 20180707,WAS 1323 | 20180707,LAN 1324 | 20180707,OAK 1325 | 20180707,DET 1326 | 20180707,HOU 1327 | 20180707,BOS 1328 | 20180707,MIN 1329 | 20180707,COL 1330 | 20180707,NYA 1331 | 20180708,SDN 1332 | 20180708,CHN 1333 | 20180708,MIL 1334 | 20180708,TBA 1335 | 20180708,PIT 1336 | 20180708,SFN 1337 | 20180708,MIA 1338 | 20180708,ANA 1339 | 20180708,OAK 1340 | 20180708,TEX 1341 | 20180708,HOU 1342 | 20180708,BOS 1343 | 20180708,MIN 1344 | 20180708,SEA 1345 | 20180708,NYA 1346 | 20180709,MIA 1347 | 20180709,NYN 1348 | 20180709,PHI 1349 | 20180709,PIT 1350 | 20180709,LAN 1351 | 20180709,SFN 1352 | 20180709,BAL 1353 | 20180709,NYA 1354 | 20180709,BOS 1355 | 20180709,CIN 1356 | 20180709,OAK 1357 | 20180709,MIN 1358 | 20180709,TBA 1359 | 20180710,TOR 1360 | 20180710,ARI 1361 | 20180710,MIL 1362 | 20180710,PHI 1363 | 20180710,WAS 1364 | 20180710,SDN 1365 | 20180710,CHN 1366 | 20180710,ANA 1367 | 20180710,BAL 1368 | 20180710,BOS 1369 | 20180710,SLN 1370 | 20180710,CIN 1371 | 20180710,HOU 1372 | 20180710,KCA 1373 | 20180710,TBA 1374 | 20180711,ATL 1375 | 20180711,COL 1376 | 20180711,MIA 1377 | 20180711,NYN 1378 | 20180711,PIT 1379 | 20180711,LAN 1380 | 20180711,SFN 1381 | 20180711,SEA 1382 | 20180711,NYA 1383 | 20180711,BOS 1384 | 20180711,CHA 1385 | 20180711,CLE 1386 | 20180711,OAK 1387 | 20180711,MIN 1388 | 20180711,TBA 1389 | 20180712,COL 1390 | 20180712,WAS 1391 | 20180712,PIT 1392 | 20180712,LAN 1393 | 20180712,ANA 1394 | 20180712,PHI 1395 | 20180712,BOS 1396 | 20180712,NYA 1397 | 20180712,OAK 1398 | 20180712,MIN 1399 | 20180713,ARI 1400 | 20180713,COL 1401 | 20180713,LAN 1402 | 20180713,PHI 1403 | 20180713,NYN 1404 | 20180713,PIT 1405 | 20180713,CHN 1406 | 20180713,SFN 1407 | 20180713,CIN 1408 | 20180713,TEX 1409 | 20180713,TOR 1410 | 20180713,CHA 1411 | 20180713,CLE 1412 | 20180713,HOU 1413 | 20180713,MIN 1414 | 20180714,ARI 1415 | 20180714,COL 1416 | 20180714,ANA 1417 | 20180714,MIA 1418 | 20180714,NYN 1419 | 20180714,PIT 1420 | 20180714,PIT 1421 | 20180714,CHN 1422 | 20180714,OAK 1423 | 20180714,CIN 1424 | 20180714,BAL 1425 | 20180714,BOS 1426 | 20180714,KCA 1427 | 20180714,NYA 1428 | 20180714,HOU 1429 | 20180714,TBA 1430 | 20180715,ATL 1431 | 20180715,COL 1432 | 20180715,LAN 1433 | 20180715,MIA 1434 | 20180715,WAS 1435 | 20180715,PIT 1436 | 20180715,CHN 1437 | 20180715,OAK 1438 | 20180715,SLN 1439 | 20180715,BAL 1440 | 20180715,BOS 1441 | 20180715,CHA 1442 | 20180715,CLE 1443 | 20180715,DET 1444 | 20180715,MIN 1445 | 20180719,CHN 1446 | 20180720,COL 1447 | 20180720,SLN 1448 | 20180720,PIT 1449 | 20180720,LAN 1450 | 20180720,PHI 1451 | 20180720,ATL 1452 | 20180720,HOU 1453 | 20180720,BOS 1454 | 20180720,KCA 1455 | 20180720,NYN 1456 | 20180720,SFN 1457 | 20180720,SEA 1458 | 20180720,MIA 1459 | 20180720,CLE 1460 | 20180720,TOR 1461 | 20180721,COL 1462 | 20180721,CHN 1463 | 20180721,SLN 1464 | 20180721,PIT 1465 | 20180721,MIL 1466 | 20180721,HOU 1467 | 20180721,DET 1468 | 20180721,KCA 1469 | 20180721,NYA 1470 | 20180721,OAK 1471 | 20180721,CHA 1472 | 20180721,MIA 1473 | 20180721,CLE 1474 | 20180721,TOR 1475 | 20180722,ARI 1476 | 20180722,CHN 1477 | 20180722,PIT 1478 | 20180722,LAN 1479 | 20180722,SDN 1480 | 20180722,PHI 1481 | 20180722,WAS 1482 | 20180722,ANA 1483 | 20180722,BOS 1484 | 20180722,KCA 1485 | 20180722,OAK 1486 | 20180722,SEA 1487 | 20180722,TBA 1488 | 20180722,TEX 1489 | 20180722,TOR 1490 | 20180723,ARI 1491 | 20180723,CIN 1492 | 20180723,ATL 1493 | 20180723,MIL 1494 | 20180723,SDN 1495 | 20180723,LAN 1496 | 20180723,CHA 1497 | 20180723,BOS 1498 | 20180723,PIT 1499 | 20180723,DET 1500 | 20180723,TBA 1501 | 20180723,OAK 1502 | 20180723,MIN 1503 | 20180724,ARI 1504 | 20180724,SLN 1505 | 20180724,HOU 1506 | 20180724,MIA 1507 | 20180724,MIL 1508 | 20180724,NYN 1509 | 20180724,PHI 1510 | 20180724,CHA 1511 | 20180724,BAL 1512 | 20180724,PIT 1513 | 20180724,KCA 1514 | 20180724,SFN 1515 | 20180724,NYA 1516 | 20180724,OAK 1517 | 20180724,MIN 1518 | 20180725,CHN 1519 | 20180725,CIN 1520 | 20180725,COL 1521 | 20180725,WAS 1522 | 20180725,NYN 1523 | 20180725,PHI 1524 | 20180725,ANA 1525 | 20180725,CLE 1526 | 20180725,DET 1527 | 20180725,SEA 1528 | 20180725,TBA 1529 | 20180725,OAK 1530 | 20180725,MIN 1531 | 20180726,LAN 1532 | 20180726,CHN 1533 | 20180726,PHI 1534 | 20180726,WAS 1535 | 20180726,NYN 1536 | 20180726,MIL 1537 | 20180726,ANA 1538 | 20180726,TBA 1539 | 20180726,MIN 1540 | 20180726,NYA 1541 | 20180726,OAK 1542 | 20180727,LAN 1543 | 20180727,CIN 1544 | 20180727,COL 1545 | 20180727,WAS 1546 | 20180727,PIT 1547 | 20180727,ARI 1548 | 20180727,MIL 1549 | 20180727,SLN 1550 | 20180727,ANA 1551 | 20180727,BAL 1552 | 20180727,BOS 1553 | 20180727,TOR 1554 | 20180727,CLE 1555 | 20180727,TEX 1556 | 20180728,LAN 1557 | 20180728,CIN 1558 | 20180728,COL 1559 | 20180728,MIA 1560 | 20180728,PIT 1561 | 20180728,ARI 1562 | 20180728,MIL 1563 | 20180728,SLN 1564 | 20180728,ANA 1565 | 20180728,BAL 1566 | 20180728,BOS 1567 | 20180728,CHA 1568 | 20180728,DET 1569 | 20180728,TEX 1570 | 20180728,KCA 1571 | 20180728,NYA 1572 | 20180729,ATL 1573 | 20180729,CIN 1574 | 20180729,COL 1575 | 20180729,MIA 1576 | 20180729,NYN 1577 | 20180729,ARI 1578 | 20180729,SFN 1579 | 20180729,CHN 1580 | 20180729,SEA 1581 | 20180729,BAL 1582 | 20180729,BOS 1583 | 20180729,TOR 1584 | 20180729,CLE 1585 | 20180729,TEX 1586 | 20180729,NYA 1587 | 20180730,TEX 1588 | 20180730,ATL 1589 | 20180730,MIL 1590 | 20180730,SFN 1591 | 20180730,SLN 1592 | 20180730,BOS 1593 | 20180730,MIN 1594 | 20180730,OAK 1595 | 20180730,SEA 1596 | 20180731,ARI 1597 | 20180731,ATL 1598 | 20180731,MIL 1599 | 20180731,PIT 1600 | 20180731,SFN 1601 | 20180731,COL 1602 | 20180731,WAS 1603 | 20180731,PHI 1604 | 20180731,KCA 1605 | 20180731,DET 1606 | 20180731,CLE 1607 | 20180731,NYA 1608 | 20180731,OAK 1609 | 20180731,HOU 1610 | 20180731,TBA 1611 | 20180801,LAN 1612 | 20180801,CHN 1613 | 20180801,SLN 1614 | 20180801,WAS 1615 | 20180801,KCA 1616 | 20180801,DET 1617 | 20180801,CLE 1618 | 20180801,BAL 1619 | 20180801,OAK 1620 | 20180801,HOU 1621 | 20180801,TBA 1622 | 20180802,SFN 1623 | 20180802,SDN 1624 | 20180802,LAN 1625 | 20180802,ATL 1626 | 20180802,PHI 1627 | 20180802,SLN 1628 | 20180802,WAS 1629 | 20180802,BOS 1630 | 20180802,CHA 1631 | 20180802,TOR 1632 | 20180802,TBA 1633 | 20180802,TEX 1634 | 20180803,ARI 1635 | 20180803,CHN 1636 | 20180803,HOU 1637 | 20180803,MIL 1638 | 20180803,ATL 1639 | 20180803,PHI 1640 | 20180803,PIT 1641 | 20180803,BOS 1642 | 20180803,ANA 1643 | 20180803,MIN 1644 | 20180803,OAK 1645 | 20180803,TOR 1646 | 20180803,CHA 1647 | 20180803,TEX 1648 | 20180804,ARI 1649 | 20180804,CHN 1650 | 20180804,HOU 1651 | 20180804,MIL 1652 | 20180804,NYN 1653 | 20180804,PHI 1654 | 20180804,SLN 1655 | 20180804,CIN 1656 | 20180804,WAS 1657 | 20180804,BOS 1658 | 20180804,CLE 1659 | 20180804,MIN 1660 | 20180804,OAK 1661 | 20180804,TOR 1662 | 20180804,CHA 1663 | 20180804,TEX 1664 | 20180805,SFN 1665 | 20180805,SDN 1666 | 20180805,LAN 1667 | 20180805,COL 1668 | 20180805,ATL 1669 | 20180805,PHI 1670 | 20180805,SLN 1671 | 20180805,WAS 1672 | 20180805,BOS 1673 | 20180805,CLE 1674 | 20180805,MIN 1675 | 20180805,OAK 1676 | 20180805,SEA 1677 | 20180805,CHA 1678 | 20180805,BAL 1679 | 20180806,ARI 1680 | 20180806,COL 1681 | 20180806,MIA 1682 | 20180806,NYN 1683 | 20180806,HOU 1684 | 20180806,ANA 1685 | 20180806,NYA 1686 | 20180806,CLE 1687 | 20180806,CHN 1688 | 20180806,SEA 1689 | 20180807,PHI 1690 | 20180807,PIT 1691 | 20180807,SLN 1692 | 20180807,SDN 1693 | 20180807,CIN 1694 | 20180807,HOU 1695 | 20180807,WAS 1696 | 20180807,ATL 1697 | 20180807,ANA 1698 | 20180807,NYA 1699 | 20180807,MIN 1700 | 20180807,CHN 1701 | 20180807,LAN 1702 | 20180807,TBA 1703 | 20180807,TEX 1704 | 20180807,BOS 1705 | 20180808,ARI 1706 | 20180808,PIT 1707 | 20180808,SLN 1708 | 20180808,MIL 1709 | 20180808,NYN 1710 | 20180808,ATL 1711 | 20180808,ANA 1712 | 20180808,NYA 1713 | 20180808,CLE 1714 | 20180808,KCA 1715 | 20180808,OAK 1716 | 20180808,BAL 1717 | 20180808,TEX 1718 | 20180808,BOS 1719 | 20180809,LAN 1720 | 20180809,SDN 1721 | 20180809,PIT 1722 | 20180809,WAS 1723 | 20180809,CLE 1724 | 20180809,SEA 1725 | 20180809,NYA 1726 | 20180809,TBA 1727 | 20180809,TOR 1728 | 20180810,ATL 1729 | 20180810,CHN 1730 | 20180810,CIN 1731 | 20180810,COL 1732 | 20180810,NYN 1733 | 20180810,SDN 1734 | 20180810,SFN 1735 | 20180810,ANA 1736 | 20180810,BOS 1737 | 20180810,CHA 1738 | 20180810,DET 1739 | 20180810,SEA 1740 | 20180810,SLN 1741 | 20180810,TEX 1742 | 20180810,TBA 1743 | 20180811,MIL 1744 | 20180811,WAS 1745 | 20180811,CIN 1746 | 20180811,COL 1747 | 20180811,MIA 1748 | 20180811,PHI 1749 | 20180811,PIT 1750 | 20180811,OAK 1751 | 20180811,BOS 1752 | 20180811,BOS 1753 | 20180811,CLE 1754 | 20180811,MIN 1755 | 20180811,SEA 1756 | 20180811,SLN 1757 | 20180811,NYA 1758 | 20180811,TBA 1759 | 20180812,ATL 1760 | 20180812,CHN 1761 | 20180812,ARI 1762 | 20180812,COL 1763 | 20180812,NYN 1764 | 20180812,SDN 1765 | 20180812,SFN 1766 | 20180812,OAK 1767 | 20180812,BOS 1768 | 20180812,CLE 1769 | 20180812,DET 1770 | 20180812,SEA 1771 | 20180812,SLN 1772 | 20180812,NYA 1773 | 20180812,TOR 1774 | 20180813,ATL 1775 | 20180813,ATL 1776 | 20180813,CLE 1777 | 20180813,SFN 1778 | 20180813,ANA 1779 | 20180813,SLN 1780 | 20180813,DET 1781 | 20180813,KCA 1782 | 20180813,NYN 1783 | 20180813,OAK 1784 | 20180813,TEX 1785 | 20180814,ATL 1786 | 20180814,MIL 1787 | 20180814,CLE 1788 | 20180814,SFN 1789 | 20180814,BOS 1790 | 20180814,ANA 1791 | 20180814,SLN 1792 | 20180814,BAL 1793 | 20180814,CHA 1794 | 20180814,COL 1795 | 20180814,TOR 1796 | 20180814,MIN 1797 | 20180814,NYA 1798 | 20180814,OAK 1799 | 20180814,ARI 1800 | 20180815,ATL 1801 | 20180815,CHN 1802 | 20180815,CLE 1803 | 20180815,LAN 1804 | 20180815,PHI 1805 | 20180815,ANA 1806 | 20180815,SLN 1807 | 20180815,NYN 1808 | 20180815,CHA 1809 | 20180815,HOU 1810 | 20180815,TOR 1811 | 20180815,MIN 1812 | 20180815,TBA 1813 | 20180815,SEA 1814 | 20180816,COL 1815 | 20180816,NYN 1816 | 20180816,PHI 1817 | 20180816,CHN 1818 | 20180816,ARI 1819 | 20180816,WAS 1820 | 20180816,KCA 1821 | 20180816,MIN 1822 | 20180816,TBA 1823 | 20180816,TEX 1824 | 20180817,COL 1825 | 20180817,CIN 1826 | 20180817,PHI 1827 | 20180817,CHN 1828 | 20180817,ARI 1829 | 20180817,SLN 1830 | 20180817,WAS 1831 | 20180817,BOS 1832 | 20180817,CHA 1833 | 20180817,CLE 1834 | 20180817,MIN 1835 | 20180817,NYA 1836 | 20180817,OAK 1837 | 20180817,LAN 1838 | 20180817,TEX 1839 | 20180818,COL 1840 | 20180818,CIN 1841 | 20180818,NYN 1842 | 20180818,PIT 1843 | 20180818,SDN 1844 | 20180818,SLN 1845 | 20180818,MIA 1846 | 20180818,BOS 1847 | 20180818,KCA 1848 | 20180818,BAL 1849 | 20180818,DET 1850 | 20180818,NYA 1851 | 20180818,OAK 1852 | 20180818,SEA 1853 | 20180818,ANA 1854 | 20180819,COL 1855 | 20180819,CIN 1856 | 20180819,NYN 1857 | 20180819,PIT 1858 | 20180819,ARI 1859 | 20180819,MIL 1860 | 20180819,MIA 1861 | 20180819,TBA 1862 | 20180819,CHA 1863 | 20180819,CLE 1864 | 20180819,MIN 1865 | 20180819,NYA 1866 | 20180819,HOU 1867 | 20180819,LAN 1868 | 20180819,TEX 1869 | 20180820,SLN 1870 | 20180820,MIL 1871 | 20180820,SFN 1872 | 20180820,ATL 1873 | 20180820,CLE 1874 | 20180820,CHA 1875 | 20180820,OAK 1876 | 20180820,SEA 1877 | 20180820,TBA 1878 | 20180820,TOR 1879 | 20180821,ARI 1880 | 20180821,SDN 1881 | 20180821,SLN 1882 | 20180821,NYA 1883 | 20180821,CIN 1884 | 20180821,NYN 1885 | 20180821,ATL 1886 | 20180821,WAS 1887 | 20180821,CLE 1888 | 20180821,MIN 1889 | 20180821,DET 1890 | 20180821,OAK 1891 | 20180821,HOU 1892 | 20180821,TBA 1893 | 20180821,TOR 1894 | 20180822,ARI 1895 | 20180822,COL 1896 | 20180822,SLN 1897 | 20180822,MIA 1898 | 20180822,MIL 1899 | 20180822,NYN 1900 | 20180822,ATL 1901 | 20180822,WAS 1902 | 20180822,BOS 1903 | 20180822,CHA 1904 | 20180822,CHN 1905 | 20180822,TEX 1906 | 20180822,HOU 1907 | 20180822,TBA 1908 | 20180822,TOR 1909 | 20180823,CHN 1910 | 20180823,COL 1911 | 20180823,ATL 1912 | 20180823,SFN 1913 | 20180823,PHI 1914 | 20180823,BOS 1915 | 20180823,DET 1916 | 20180823,MIN 1917 | 20180823,TBA 1918 | 20180824,SEA 1919 | 20180824,CHN 1920 | 20180824,SLN 1921 | 20180824,LAN 1922 | 20180824,MIA 1923 | 20180824,MIL 1924 | 20180824,NYN 1925 | 20180824,TEX 1926 | 20180824,HOU 1927 | 20180824,NYA 1928 | 20180824,CHA 1929 | 20180824,KCA 1930 | 20180824,OAK 1931 | 20180824,TBA 1932 | 20180824,TOR 1933 | 20180825,SEA 1934 | 20180825,CHN 1935 | 20180825,COL 1936 | 20180825,LAN 1937 | 20180825,MIA 1938 | 20180825,PIT 1939 | 20180825,NYN 1940 | 20180825,SFN 1941 | 20180825,HOU 1942 | 20180825,NYA 1943 | 20180825,NYA 1944 | 20180825,CHA 1945 | 20180825,KCA 1946 | 20180825,OAK 1947 | 20180825,TBA 1948 | 20180825,TOR 1949 | 20180826,ARI 1950 | 20180826,CHN 1951 | 20180826,SLN 1952 | 20180826,LAN 1953 | 20180826,ATL 1954 | 20180826,MIL 1955 | 20180826,WAS 1956 | 20180826,SFN 1957 | 20180826,HOU 1958 | 20180826,NYA 1959 | 20180826,CHA 1960 | 20180826,CLE 1961 | 20180826,OAK 1962 | 20180826,TBA 1963 | 20180826,PHI 1964 | 20180827,CHN 1965 | 20180827,WAS 1966 | 20180827,SFN 1967 | 20180827,ANA 1968 | 20180827,BAL 1969 | 20180827,HOU 1970 | 20180827,CHA 1971 | 20180828,ATL 1972 | 20180828,CHN 1973 | 20180828,CIN 1974 | 20180828,WAS 1975 | 20180828,SDN 1976 | 20180828,SFN 1977 | 20180828,SLN 1978 | 20180828,COL 1979 | 20180828,BAL 1980 | 20180828,BOS 1981 | 20180828,CLE 1982 | 20180828,OAK 1983 | 20180828,KCA 1984 | 20180828,NYA 1985 | 20180828,LAN 1986 | 20180829,TBA 1987 | 20180829,NYN 1988 | 20180829,MIL 1989 | 20180829,PHI 1990 | 20180829,SDN 1991 | 20180829,ARI 1992 | 20180829,PIT 1993 | 20180829,BAL 1994 | 20180829,BOS 1995 | 20180829,MIN 1996 | 20180829,HOU 1997 | 20180829,KCA 1998 | 20180829,CHA 1999 | 20180829,LAN 2000 | 20180830,CHN 2001 | 20180830,MIL 2002 | 20180830,ARI 2003 | 20180830,SDN 2004 | 20180830,SLN 2005 | 20180830,BOS 2006 | 20180830,CLE 2007 | 20180830,ANA 2008 | 20180830,DET 2009 | 20180830,SEA 2010 | 20180831,PIT 2011 | 20180831,LAN 2012 | 20180831,TOR 2013 | 20180831,PHI 2014 | 20180831,SDN 2015 | 20180831,SFN 2016 | 20180831,SLN 2017 | 20180831,MIL 2018 | 20180831,CHA 2019 | 20180831,CLE 2020 | 20180831,ANA 2021 | 20180831,KCA 2022 | 20180831,NYA 2023 | 20180831,OAK 2024 | 20180831,MIN 2025 | 20180901,ATL 2026 | 20180901,LAN 2027 | 20180901,MIA 2028 | 20180901,CHN 2029 | 20180901,COL 2030 | 20180901,NYN 2031 | 20180901,CIN 2032 | 20180901,WAS 2033 | 20180901,BOS 2034 | 20180901,TBA 2035 | 20180901,HOU 2036 | 20180901,KCA 2037 | 20180901,NYA 2038 | 20180901,SEA 2039 | 20180901,TEX 2040 | 20180902,ATL 2041 | 20180902,LAN 2042 | 20180902,TOR 2043 | 20180902,CHN 2044 | 20180902,COL 2045 | 20180902,NYN 2046 | 20180902,CIN 2047 | 20180902,MIL 2048 | 20180902,CHA 2049 | 20180902,TBA 2050 | 20180902,HOU 2051 | 20180902,KCA 2052 | 20180902,DET 2053 | 20180902,OAK 2054 | 20180902,TEX 2055 | 20180903,SDN 2056 | 20180903,BOS 2057 | 20180903,COL 2058 | 20180903,NYN 2059 | 20180903,MIA 2060 | 20180903,MIL 2061 | 20180903,PIT 2062 | 20180903,WAS 2063 | 20180903,CHA 2064 | 20180903,KCA 2065 | 20180903,HOU 2066 | 20180903,OAK 2067 | 20180903,SEA 2068 | 20180903,ANA 2069 | 20180903,TBA 2070 | 20180904,ARI 2071 | 20180904,BOS 2072 | 20180904,COL 2073 | 20180904,LAN 2074 | 20180904,PHI 2075 | 20180904,MIL 2076 | 20180904,PIT 2077 | 20180904,SLN 2078 | 20180904,DET 2079 | 20180904,CLE 2080 | 20180904,HOU 2081 | 20180904,NYA 2082 | 20180904,BAL 2083 | 20180904,TEX 2084 | 20180904,TBA 2085 | 20180905,BOS 2086 | 20180905,COL 2087 | 20180905,NYN 2088 | 20180905,MIA 2089 | 20180905,CHN 2090 | 20180905,PIT 2091 | 20180905,SLN 2092 | 20180905,DET 2093 | 20180905,CLE 2094 | 20180905,HOU 2095 | 20180905,OAK 2096 | 20180905,SEA 2097 | 20180905,ANA 2098 | 20180905,TOR 2099 | 20180906,ATL 2100 | 20180906,SDN 2101 | 20180906,CHN 2102 | 20180906,CLE 2103 | 20180907,ARI 2104 | 20180907,CIN 2105 | 20180907,LAN 2106 | 20180907,MIL 2107 | 20180907,PHI 2108 | 20180907,PIT 2109 | 20180907,HOU 2110 | 20180907,ANA 2111 | 20180907,DET 2112 | 20180907,MIN 2113 | 20180907,OAK 2114 | 20180907,NYA 2115 | 20180907,TBA 2116 | 20180907,TOR 2117 | 20180908,ATL 2118 | 20180908,CIN 2119 | 20180908,COL 2120 | 20180908,MIL 2121 | 20180908,NYN 2122 | 20180908,PIT 2123 | 20180908,WAS 2124 | 20180908,WAS 2125 | 20180908,HOU 2126 | 20180908,ANA 2127 | 20180908,DET 2128 | 20180908,KCA 2129 | 20180908,OAK 2130 | 20180908,NYA 2131 | 20180908,TBA 2132 | 20180908,CLE 2133 | 20180909,ATL 2134 | 20180909,SDN 2135 | 20180909,LAN 2136 | 20180909,MIL 2137 | 20180909,NYN 2138 | 20180909,BOS 2139 | 20180909,ANA 2140 | 20180909,SLN 2141 | 20180909,MIN 2142 | 20180909,OAK 2143 | 20180909,SEA 2144 | 20180909,TBA 2145 | 20180909,TOR 2146 | 20180910,MIL 2147 | 20180910,CIN 2148 | 20180910,COL 2149 | 20180910,ATL 2150 | 20180910,SLN 2151 | 20180910,TEX 2152 | 20180910,HOU 2153 | 20180910,KCA 2154 | 20180910,NYA 2155 | 20180910,TBA 2156 | 20180911,CHN 2157 | 20180911,CIN 2158 | 20180911,ARI 2159 | 20180911,MIA 2160 | 20180911,WAS 2161 | 20180911,WAS 2162 | 20180911,ATL 2163 | 20180911,SLN 2164 | 20180911,ANA 2165 | 20180911,OAK 2166 | 20180911,BOS 2167 | 20180911,HOU 2168 | 20180911,KCA 2169 | 20180911,MIN 2170 | 20180911,SDN 2171 | 20180911,CLE 2172 | 20180912,MIL 2173 | 20180912,LAN 2174 | 20180912,COL 2175 | 20180912,NYN 2176 | 20180912,WAS 2177 | 20180912,ATL 2178 | 20180912,PIT 2179 | 20180912,ANA 2180 | 20180912,OAK 2181 | 20180912,BOS 2182 | 20180912,HOU 2183 | 20180912,CHA 2184 | 20180912,MIN 2185 | 20180912,SDN 2186 | 20180912,TBA 2187 | 20180913,COL 2188 | 20180913,NYN 2189 | 20180913,NYN 2190 | 20180913,LAN 2191 | 20180913,CHN 2192 | 20180913,SEA 2193 | 20180913,BAL 2194 | 20180913,BOS 2195 | 20180913,KCA 2196 | 20180914,ATL 2197 | 20180914,CHN 2198 | 20180914,MIL 2199 | 20180914,PHI 2200 | 20180914,TEX 2201 | 20180914,SFN 2202 | 20180914,LAN 2203 | 20180914,SEA 2204 | 20180914,CHA 2205 | 20180914,NYN 2206 | 20180914,DET 2207 | 20180914,ARI 2208 | 20180914,KCA 2209 | 20180914,NYA 2210 | 20180914,OAK 2211 | 20180915,WAS 2212 | 20180915,CHN 2213 | 20180915,PIT 2214 | 20180915,PHI 2215 | 20180915,TEX 2216 | 20180915,SFN 2217 | 20180915,LAN 2218 | 20180915,SEA 2219 | 20180915,CHA 2220 | 20180915,BOS 2221 | 20180915,CLE 2222 | 20180915,HOU 2223 | 20180915,KCA 2224 | 20180915,TOR 2225 | 20180915,TBA 2226 | 20180916,WAS 2227 | 20180916,CIN 2228 | 20180916,PIT 2229 | 20180916,MIA 2230 | 20180916,SDN 2231 | 20180916,COL 2232 | 20180916,SLN 2233 | 20180916,ANA 2234 | 20180916,BAL 2235 | 20180916,BOS 2236 | 20180916,DET 2237 | 20180916,HOU 2238 | 20180916,MIN 2239 | 20180916,TOR 2240 | 20180916,TBA 2241 | 20180917,CHN 2242 | 20180917,SLN 2243 | 20180917,LAN 2244 | 20180917,MIA 2245 | 20180917,MIL 2246 | 20180917,NYN 2247 | 20180917,PIT 2248 | 20180917,SFN 2249 | 20180917,TOR 2250 | 20180917,MIN 2251 | 20180917,SEA 2252 | 20180917,TBA 2253 | 20180918,CHN 2254 | 20180918,SLN 2255 | 20180918,LAN 2256 | 20180918,WAS 2257 | 20180918,CIN 2258 | 20180918,PHI 2259 | 20180918,PIT 2260 | 20180918,SFN 2261 | 20180918,TOR 2262 | 20180918,CLE 2263 | 20180918,MIN 2264 | 20180918,HOU 2265 | 20180918,NYA 2266 | 20180918,ANA 2267 | 20180918,TBA 2268 | 20180919,ARI 2269 | 20180919,ATL 2270 | 20180919,LAN 2271 | 20180919,MIL 2272 | 20180919,PHI 2273 | 20180919,PIT 2274 | 20180919,SDN 2275 | 20180919,BAL 2276 | 20180919,CLE 2277 | 20180919,MIN 2278 | 20180919,SEA 2279 | 20180919,NYA 2280 | 20180919,OAK 2281 | 20180919,TBA 2282 | 20180920,ATL 2283 | 20180920,CIN 2284 | 20180920,NYN 2285 | 20180920,CHA 2286 | 20180920,DET 2287 | 20180920,BOS 2288 | 20180920,OAK 2289 | 20180920,TOR 2290 | 20180921,COL 2291 | 20180921,ATL 2292 | 20180921,SDN 2293 | 20180921,MIA 2294 | 20180921,MIL 2295 | 20180921,SLN 2296 | 20180921,NYN 2297 | 20180921,CHA 2298 | 20180921,BOS 2299 | 20180921,KCA 2300 | 20180921,HOU 2301 | 20180921,NYA 2302 | 20180921,OAK 2303 | 20180921,TEX 2304 | 20180921,TBA 2305 | 20180922,COL 2306 | 20180922,ATL 2307 | 20180922,LAN 2308 | 20180922,MIA 2309 | 20180922,PIT 2310 | 20180922,SLN 2311 | 20180922,WAS 2312 | 20180922,CHN 2313 | 20180922,CLE 2314 | 20180922,DET 2315 | 20180922,HOU 2316 | 20180922,NYA 2317 | 20180922,OAK 2318 | 20180922,SEA 2319 | 20180922,TOR 2320 | 20180923,COL 2321 | 20180923,ATL 2322 | 20180923,LAN 2323 | 20180923,MIA 2324 | 20180923,MIL 2325 | 20180923,SLN 2326 | 20180923,NYN 2327 | 20180923,CHN 2328 | 20180923,CLE 2329 | 20180923,KCA 2330 | 20180923,HOU 2331 | 20180923,BAL 2332 | 20180923,MIN 2333 | 20180923,TEX 2334 | 20180923,TBA 2335 | 20180924,LAN 2336 | 20180924,PIT 2337 | 20180924,COL 2338 | 20180924,SDN 2339 | 20180924,MIL 2340 | 20180924,WAS 2341 | 20180924,ANA 2342 | 20180924,BOS 2343 | 20180924,CLE 2344 | 20180924,OAK 2345 | 20180924,NYA 2346 | 20180924,HOU 2347 | 20180925,ARI 2348 | 20180925,PIT 2349 | 20180925,KCA 2350 | 20180925,COL 2351 | 20180925,ATL 2352 | 20180925,SFN 2353 | 20180925,MIL 2354 | 20180925,WAS 2355 | 20180925,ANA 2356 | 20180925,CHA 2357 | 20180925,DET 2358 | 20180925,SEA 2359 | 20180925,NYA 2360 | 20180925,HOU 2361 | 20180926,ARI 2362 | 20180926,CHN 2363 | 20180926,KCA 2364 | 20180926,COL 2365 | 20180926,NYN 2366 | 20180926,SDN 2367 | 20180926,MIL 2368 | 20180926,WAS 2369 | 20180926,ANA 2370 | 20180926,BOS 2371 | 20180926,BAL 2372 | 20180926,CLE 2373 | 20180926,MIN 2374 | 20180926,OAK 2375 | 20180926,TBA 2376 | 20180926,TOR 2377 | 20180927,CHN 2378 | 20180927,COL 2379 | 20180927,NYN 2380 | 20180927,KCA 2381 | 20180927,MIN 2382 | 20180927,TEX 2383 | 20180927,NYA 2384 | 20180928,CHN 2385 | 20180928,PIT 2386 | 20180928,COL 2387 | 20180928,MIL 2388 | 20180928,MIA 2389 | 20180928,ATL 2390 | 20180928,SDN 2391 | 20180928,LAN 2392 | 20180928,ANA 2393 | 20180928,HOU 2394 | 20180928,NYA 2395 | 20180928,CLE 2396 | 20180928,MIN 2397 | 20180928,MIN 2398 | 20180928,SEA 2399 | 20180928,TOR 2400 | 20180929,SLN 2401 | 20180929,CIN 2402 | 20180929,WAS 2403 | 20180929,MIL 2404 | 20180929,NYN 2405 | 20180929,PHI 2406 | 20180929,ARI 2407 | 20180929,LAN 2408 | 20180929,OAK 2409 | 20180929,HOU 2410 | 20180929,HOU 2411 | 20180929,NYA 2412 | 20180929,KCA 2413 | 20180929,MIN 2414 | 20180929,SEA 2415 | 20180929,TBA 2416 | 20180930,CHN 2417 | 20180930,PIT 2418 | 20180930,COL 2419 | 20180930,MIL 2420 | 20180930,NYN 2421 | 20180930,PHI 2422 | 20180930,SDN 2423 | 20180930,LAN 2424 | 20180930,ANA 2425 | 20180930,BAL 2426 | 20180930,BOS 2427 | 20180930,CLE 2428 | 20180930,MIN 2429 | 20180930,SEA 2430 | 20180930,TBA 2431 | 20181001,MIL 2432 | 20181001,LAN 2433 | --------------------------------------------------------------------------------