Public
Edited
Feb 28, 2024
Insert cell
Insert cell
Insert cell
nbaLocations = FileAttachment("nba_team_locations-4.csv")
.csv({ typed: true })
.then((data) => data.map((d) => ({ ...d, Year: new Date(d['Opening Year'], 0) })))
Insert cell
usBoundaries = FileAttachment("us-10m.json").json()
Insert cell
nbaColorsAndLogos = FileAttachment("nba_color_codes-1.csv").csv({typed: true})
Insert cell
Insert cell
{
const teamLocations = vl.markPoint()
.data(nbaLocations)
.encode(
vl.x().fieldQ('Long').scale({domain: [-125, -60]}),
vl.y().fieldQ('Lat').scale({domain: [25, 48]}),
vl.color().fieldN('Region')
);

const teamLablels = vl.markText({align: 'left', dx: 5, dy: 5})
.data(nbaLocations)
.encode(
vl.x().fieldQ('Long').scale({domain: [-125, -60]}),
vl.y().fieldQ('Lat').scale({domain: [25, 48]}),
vl.text().fieldN('Team')
);

return vl.layer(teamLablels, teamLocations).render()
}
Insert cell
{
const regionSelector = vl.selectPoint()
.fields('Region')
.on('mouseover')
.clear('mousehover')
.nearest(true)
const teamLocations = vl.markPoint()
.encode(
vl.longitude().fieldQ('Long'),
vl.latitude().fieldQ('AdjustedLat'),
vl.size().fieldQ('City Population'),
vl.color().fieldN('Region'),
);

const teamLablels = vl.markText({align: 'left', dx: 5, dy: 5})
.params(regionSelector)
.encode(
vl.longitude().fieldQ('Long'),
vl.latitude().fieldQ('AdjustedLat'),
vl.text().fieldN('Team'),
vl.color().fieldN('Region').scale({scheme: 'category10'}),
vl.opacity().if(regionSelector, vl.value(1.0)).value(0.2)
);

const teamLogos = vl.markImage({width: 25, height: 20})
.transform(
vl.lookup("Team").from(vl.data(nbaColorsAndLogos).key("Team").fields(["LogoSvgUrl"]))
)
.encode(
vl.longitude().fieldQ("Long"),
vl.latitude().fieldQ("AdjustedLat"),
vl.url().fieldN("LogoSvgUrl")
)

const teamMap = vl.markGeoshape({fill: '#d3d3d3', stroke: '#A9A9A9'})
.data(vl.topojson(usBoundaries).feature('states'))

return vl.layer(teamMap, teamLablels, teamLogos)
.data(nbaLocations)
.project(vl.projection('albersUSA'))
.width(700)
.height(700)
.render()
}
Insert cell
{
// FOR LATER - IGNORE FOR NOW :)
// Create an adjusted
for(let nbaLoc of nbaLocations){
nbaLoc.AdjustedLat = nbaLoc.Lat;
if(nbaLoc.Team.includes("Clippers")){
nbaLoc.AdjustedLat += -0.6;
}else if(nbaLoc.Team.includes("Nets")){
nbaLoc.AdjustedLat += -0.3;
}else if(nbaLoc.Team.includes("Knicks")){
nbaLoc.AdjustedLat += 0.2;
}else if(nbaLoc.Team.includes("Bucks")){
nbaLoc.AdjustedLat += 0.2;
}else if(nbaLoc.Team.includes("Pistons")){
nbaLoc.AdjustedLat -= 0.1;
}else if(nbaLoc.Team.includes("Spurs")){
nbaLoc.AdjustedLat -= 0.4;
}else if(nbaLoc.Team.includes("Thunder")){
nbaLoc.AdjustedLat += 0.2;
}
}
return nbaLocations; // an optional return (just makes it easier to see data)
}
Insert cell
Insert cell
import {vl} from "@vega/vega-lite-api-v5"
Insert cell
import {toc} from "@jonfroehlich/collapsible-toc"
Insert cell
import {printVegaLiteJSON} from "@jonfroehlich/vega-lite-utilities"
Insert cell
import {printTable} from "@jonfroehlich/data-utilities"
Insert cell
import {printTableTypes} from "@jonfroehlich/data-utilities"
Insert cell
import {mean} from "@jonfroehlich/data-utilities"
Insert cell
import {median} from "@jonfroehlich/data-utilities"
Insert cell
import {standardDeviation} from "@jonfroehlich/data-utilities"
Insert cell
import {countOccurrencesMap} from "@jonfroehlich/data-utilities"
Insert cell
import {vegalite} from "@jonfroehlich/vega-lite-utilities"
Insert cell
// https://github.com/dcousens/haversine-distance
haversine = require('https://bundle.run/haversine-distance@1.2.1')
Insert cell
{
// FOR LATER - IGNORE FOR NOW :)
// Create an adjusted
for(let nbaLoc of nbaLocations){
nbaLoc.AdjustedLat = nbaLoc.Lat;
if(nbaLoc.Team.includes("Clippers")){
nbaLoc.AdjustedLat += -0.6;
}else if(nbaLoc.Team.includes("Nets")){
nbaLoc.AdjustedLat += -0.3;
}else if(nbaLoc.Team.includes("Knicks")){
nbaLoc.AdjustedLat += 0.2;
}else if(nbaLoc.Team.includes("Bucks")){
nbaLoc.AdjustedLat += 0.2;
}else if(nbaLoc.Team.includes("Pistons")){
nbaLoc.AdjustedLat -= 0.1;
}else if(nbaLoc.Team.includes("Spurs")){
nbaLoc.AdjustedLat -= 0.4;
}else if(nbaLoc.Team.includes("Thunder")){
nbaLoc.AdjustedLat += 0.2;
}
}
return nbaLocations; // an optional return (just makes it easier to see data)
}
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