Published
Edited
Apr 6, 2021
Insert cell
md`# Day 5 - Slope`
Insert cell
html`Every MLB Teams Player Movement from Team to Team 2019-2020`
Insert cell
chart = {
const margin = { top: 30, right: 15, bottom: 30, left: 30 };
const markerBoxWidth = 6;
const markerBoxHeight = 6;
const refX = 24;
const refY = markerBoxHeight / 2;
const arrowPoints = [[0, 0], [0, markerBoxWidth], [markerBoxWidth, markerBoxWidth/2]];
const width = 800 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
const svg = d3.create('svg')
.attr('width',width + margin.left + margin.right)
.attr('height',height + margin.top + margin.bottom);
const graph = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const y1 = d3.scaleBand().range([height,0]).domain(teams.map(d => d.team_id));
const r = d3.scaleLinear().range([15,15]).domain([35,60]);
const links = _.filter(_.cloneDeep(players), d=>d.teams.length>1)

var playerLinks = graph.selectAll('link')
.data(links)
.enter()
.append("g");
const l = d3.line().curve(d3.curveNatural);
let count = 0;
playerLinks.selectAll('connections')
.data(d=>d.teams)
.enter()
.append("path")
.attr("class",d=>`team team_${d.split('-')[1]}`)
.attr("d",(d,k,j)=> {
// split out team id from id for connection
const parentData = JSON.parse(JSON.stringify(j)).map(i => { return i.__data__.split('-')[1] });
let t = k+1;
if (t<parentData.length) {
const pathHeight = (count%2==0) ? 0 + Math.floor(Math.random() * 100) + 1 : height - Math.floor(Math.random() * 100) + 1;
count++;
const points = [];
points.push([width/4,y1(parentData[t-1])])
const team1 = parentData[t-1];
const team2 = parentData[t];

if (team1 != team2) {
points.push([width*.75, y1(parentData[t])]);
return l(points);
}
return null
}
})
.attr("opacity",d=> .25)
.attr("fill",'none')
.attr("stroke",d=> {
return '#' + teamCount[d.split('-')[1]][0].parent_color
})
.attr("stroke-width",2)

const gTeamStart = graph.selectAll('teams-start')
.data(teams)
.enter()
.append("g")
.attr("transform",d=>`translate(${width/4},${y1(d.team_id)})`);
gTeamStart.append("circle")
.attr("id",d=>`id_${d.team_id}`)
.attr("r",d=>r(teamCount[d.team_id].length))
.attr("fill","#fff")
.attr("stroke",d=>`#${d.parent_color}`)
gTeamStart.append("image")
.attr("href",d=>`https://www.mlbstatic.com/team-logos/${d.team_id}.svg`)
.attr("height",16)
.attr("x",-10)
.attr("y",-10);
const gTeamEnd = graph.selectAll('teams-end')
.data(teams)
.enter()
.append("g")
.attr("transform",d=>`translate(${width*.75},${y1(d.team_id)})`);
gTeamEnd.append("circle")
.attr("id",d=>`id_${d.team_id}`)
.attr("r",d=>r(teamCount[d.team_id].length))
//.attr("fill",d=>`#${d.secondary_color}`)
.attr("fill","#fff")
.attr("stroke",d=>`#${d.parent_color}`)
gTeamEnd.append("image")
.attr("href",d=>`https://www.mlbstatic.com/team-logos/${d.team_id}.svg`)
.attr("height",16)
.attr("x",-10)
.attr("y",-10);
return svg.node();
}
Insert cell
teamCount = _.groupBy(players,'team_id')
Insert cell
teams = _.uniqBy(players, 'team_id');
Insert cell
players = {
const data = await FileAttachment('players@6.json').json();
const players = data.players;
console.log(players);
return _.shuffle(_.uniqBy(_.map(players, d=> {
d.teams = JSON.parse(d.teams);
return d;
}),'player_id'));
}
Insert cell
_ = require('lodash');
Insert cell
d3 = require('d3');
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more