Published
Edited
Oct 17, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = FileAttachment("mls-salaries-2017.csv").csv()
Insert cell
x_variable = _.uniqBy(data.map(d => d.position))
Insert cell
y_variable = _.uniqBy(data.map(d => d.base_salary))
Insert cell
color_variable = _.uniqBy(data.map(d => d.position))
Insert cell
cleaned_data = d3.rollup(
data,
v => d3.mean(v, d => d.base_salary),
d => d.club,
d => d.position
)
Insert cell
function unroll(rollup, keys, label = "value", p = {}) {
return Array.from(rollup, ([key, value]) =>
value instanceof Map
? unroll(
value,
keys.slice(1),
label,
Object.assign({}, { ...p, [keys[0]]: key })
)
: Object.assign({}, { ...p, [keys[0]]: key, [label]: value })
).flat();
}
Insert cell
chart_data = unroll(cleaned_data, ["club", "x"], "y")
Insert cell
Insert cell
clubs = _.uniqBy(data.map(d => d.club))
Insert cell
x_domain = _.uniqBy(data.map(d => d.position))
Insert cell
y_domain = d3.extent(chart_data.map(d => +d.y))
Insert cell
margin = ({ top: 20, right: 30, bottom: 50, left: 80 })
Insert cell
height = 500
Insert cell
x_scale = d3
.scaleBand()
.domain(x_domain)
.range([margin.left, width - margin.right])
.paddingInner(0.2)
Insert cell
y_scale = d3
.scaleLinear()
.domain(y_domain)
.range([height - margin.bottom, margin.top])
Insert cell
color_scale = d3.scaleOrdinal(x_domain, d3.schemeTableau10)
Insert cell
Insert cell
{
const svg = d3.create('svg').attr('viewBox', [0, 0, width, height]);
svg
.append('g')
.call(g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x_scale))
);
return svg.node();
}
Insert cell
{
const svg = d3.create('svg').attr('viewBox', [0, 0, width, height]);
svg
.append('g')
.call(g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y_scale))
);
return svg.node();
}
Insert cell
import { legend } from "@d3/color-legend"
Insert cell
color = legend({
color: color_scale,
title: "Position",
width: width
})
Insert cell
xyaxes = {
const svg = d3.create('svg').attr('viewBox', [0, 0, width, height]);
svg
.append('g')
.call(g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y_scale))
);
svg
.append('g')
.call(g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x_scale))
);
return svg.node();
}
Insert cell
Insert cell
x_chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const selection = svg.selectAll('.bar');
const bars = selection.data(chart_data.filter(d => d.club == team));
bars
.join(
enter =>
enter
.append('rect')
.style('opacity', 1)
.attr('x', d => x_scale(d.x))
.attr('width', x_scale.bandwidth())
.attr('fill', d => color_scale(d.x))
.style('opacity', 1),
exit => exit.remove()
)
.transition()
.attr('height', d => 10)
.duration(2000);
// };

return svg.node();
}
Insert cell
y_chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const selection = svg.selectAll('.bar');
const bars = selection.data(chart_data.filter(d => d.club == team));
bars
.join(
enter =>
enter
.append('rect')
.style('opacity', 1)
.attr('y', height - margin.bottom)
.attr('width', x_scale.bandwidth())
.style('opacity', 1),
exit => exit.remove()
)
.transition()
.attr('height', d => height - margin.bottom - y_scale(d.y))
.attr('y', d => y_scale(d.y))
.duration(2000);
// };

return svg.node();
}
Insert cell
xy_chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const selection = svg.selectAll('.bar');
const bars = selection.data(chart_data.filter(d => d.club == team));
bars
.join(
enter =>
enter
.append('rect')
.style('opacity', 1)
.attr('x', d => x_scale(d.x))
.attr('y', height - margin.bottom)
.attr('width', x_scale.bandwidth())
.attr('fill', d => color_scale(d.x))
.style('opacity', 1),
exit => exit.remove()
)
.transition()
.attr('height', d => height - margin.bottom - y_scale(d.y))
.attr('y', d => y_scale(d.y))
.duration(2000);
// };

return svg.node();
}
Insert cell
Insert cell
import { select } from "@jashkenas/inputs"
Insert cell
viewof team = select(clubs)
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
//Title
svg
.append("text")
.attr("x", width / 2)
.attr("y", margin.top / 1.5)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Soccer Team's Position's Average Salary per Team");

//x axis
svg
.append('g')
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x_scale))
)
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', "-0.8em")
.attr("dy", "0.15em")
.attr('transform', "rotate(-45)");
svg
.append("text")
.attr('text-anchor', 'middle')
.attr('x', (width + margin.left) / 2)
.attr('y', height - 10)
.text('Player Position');

//y axis
svg
.append('g')
.call(g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y_scale))
);
svg
.append("text")
.attr("y", margin.left / 2 - 20)
.attr("x", -(height - margin.bottom) / 2)
.style("text-anchor", "middle")
.text("Average Salary")
.attr('transform', "rotate(-90)");

const selection = svg.selectAll('.bar');
const bars = selection.data(chart_data.filter(d => d.club == team));
bars
.join(
enter =>
enter
.append('rect')
.style('opacity', 1)
.attr('x', d => x_scale(d.x))
.attr('y', height - margin.bottom)
.attr('width', x_scale.bandwidth())
.attr('fill', d => color_scale(d.x))
.style('opacity', 1),
exit => exit.remove()
)
.transition()
.attr('height', d => height - margin.bottom - y_scale(d.y))
.attr('y', d => y_scale(d.y))
.duration(2000);

return svg.node();
}
Insert cell
Insert cell
md`The code explained in the class I feel like wasn't enough. If the lectures or labs went over the code that we need for the class, that would be fantastic.`
Insert cell
Insert cell
import {
assignment_instructions,
observable_challenges
} from "@uw-info474/utilities"
Insert cell
Insert cell
Insert cell
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