Public
Edited
Jun 19, 2023
Insert cell
Insert cell
bundesliga_players.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
height = 400
Insert cell
margin = ({top: 30, right: 60, bottom: 30, left: 60})
Insert cell
data = FileAttachment("bundesliga_players.csv").csv(function(d) {salary: parseFloat(d.salary)})
Insert cell
x = d3.scaleLinear()
.domain(d3.extent(data, d => d.salary)).nice()
.range([margin.left, width - margin.right])
Insert cell
x2 = d3.scaleLinear()
.domain(d3.extent(data, d => d.max_salary)).nice()
.range([margin.left, width - margin.right])
Insert cell
chart1 = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, 100])
.style("overflow", "visible");

svg
.selectAll("rect")
.data(data)
.join("rect")
.attr("class", "transition")
.attr("x", (d) => x(d.salary))
.attr("y", 10)
.attr("width", 0.5)
.attr("height", 40)
.attr("opacity", 0.8)
.style("fill", "#1ce3cd")
.transition()
.duration(3000)
.delay((d, i) => i * 5)
.attr("x", (d) => x2(d.salary));

svg
.selectAll("text")
.data(data)
.join("text")
.attr("x", width / 2 - 50)
.attr("y", 85)
.transition()
.duration(3000);

return svg.node();
}
Insert cell
chart2 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible");

let y = d3.scaleLinear()
.domain(d3.extent(data, d => d.salary))
.nice()
.range([height - margin.bottom, margin.top]);

svg.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x(d.max_salary))
.attr("y", 0)
.attr("width", 1)
.attr("height", 40)
.style("fill", "#f20666")
.transition()
.duration(5000)
.attr("y", d => y(d.salary))
.attr("height", 3)
.attr("width", 3)
.attr("rx", 3)
.attr("ry", 3);

svg.selectAll("text")
.data(data)
.join("text")
.attr("x", 0)
.attr("y", 200)
.attr("opacity", 0)
.text("Salary")
.transition()
.delay(5000)
.duration(2000)
.attr("opacity", 1);

return svg.node();
}
Insert cell
scatterplot2 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible");

svg.selectAll("circle")
.data(data)
.join("circle")
.filter(d => d.salary > 3.5)
.attr("cx", d => x_scaled(d.salary))
.attr("cy", d => y(d.age))
.attr("r", d => r(d.player_height))
.attr("fill", d => c(d.salary))
.transition()
.duration(3000)
.attr("r", d => r(d.player_height))
.attr("cx", d => x_scaled(d.max_salary));

svg.selectAll("text")
.data(data)
.join("text")
.filter(d => d.player_height > 1.90)
.text(d => d.player_height)
.attr("x", d => x_scaled(d.salary) - 7)
.attr("y", d => y(d.age) + 3)
.transition()
.duration(3000)
.attr("x", d => x_scaled(d.max_salary) - 7)
.attr("y", d => y(d.age) + 3);

svg.append("g")
.call(yAxis);
svg.append("g")
.call(xAxis);

return svg.node();
}
Insert cell
extent_salary = d3.extent(data, (d) => d.salary)
Insert cell
max = d3.max(data, d => d.salary)
Insert cell
barcode = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, 150])
.style("overflow", "visible");
svg.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => d.salary)
.attr("y", 20)
.attr("width", 1)
.attr("height", 100);

return svg.node();
}
Insert cell
x_scaled = d3
.scaleLinear()
//.domain(d3.extent(data, (d) => d.salary))
.domain([0, d3.max(data, (d) => d.salary)])
.range([margin.left, width - margin.right])
Insert cell
y = d3.scaleBand()
.domain(data.map(d => d.age).sort(d3.ascending))
.rangeRound([margin.top, height - margin.bottom])
.padding(0);
Insert cell
xAxis = (g) => g
.attr("class", "x-axis")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3
.axisBottom()
.scale(x_scaled)
.ticks(10)
.tickPadding(0))
Insert cell
yAxis = (g) => g
.attr("class", "y-axis")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft()
.scale(y)
.ticks(10)
.tickSize(-width)
.tickPadding(5)
)
Insert cell
barcode_scaled = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible");
svg.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x_scaled(d.salary))
.attr("y", 20)
.attr("width", 2)
.attr("height", height-margin.bottom*1.75);

svg
.append("g")
.call(xAxis);
return svg.node();
}
Insert cell
c = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d.salary))
.range(["#022859", "#cd1717"])
Insert cell
barcode2 = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, 400])
.style("overflow", "visible");

svg
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", (d) => x_scaled(d.salary))
.attr("y", 20)
.attr("width", 2)
.attr("height", height-margin.bottom*1.75)
.attr("fill", (d) => c(d.salary));

svg
.append("g")
.call(xAxis);
return svg.node();
}
Insert cell
r = d3
.scaleSqrt()
.domain(d3.extent(data, (d) => d.player_height))
.range([2, 30])
Insert cell
scatterplot = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible");

svg
.selectAll("circle")
.data(data)
.join("circle")
.filter((d) => (d.salary > 3.5))
.attr("cx", (d) => x_scaled(d.salary))
.attr("cy", (d) => y(d.age))
.attr("r", (d) => r(d.player_height))
.attr("fill", (d) => c(d.salary));
svg
.selectAll("text")
.data(data)
.join("text")
.filter((d) => d.player_height > 1.90)
.text((d) => d.player_height)
.attr("x", (d) => x_scaled(d.salary)-7)
.attr("y", (d) => y(d.age)+3)
//.attr("x", 100)
//.attr("y", 100)
svg
.append("g")
.call(yAxis);
svg
.append("g")
.call(xAxis);
return svg.node();
}
Insert cell
style2 = html'<style>

@import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100;0,300;1,100;1,300&display=swap");

body {
font-family: 'Montserrat Alternates', sans-serif;
font-weight:400;
font-size:13px;
background-color:white;
}

svg {
background-color:white;
}

/*Defining test stylings*/

h1 {
margin-top: 50;
font-size: 1.3rem;
margin-bottom: 50;
font-weight:600;
}

h2 {
margin-top: 5px;
font-size: 1.1rem;
margin-bottom: 5px;
color:#f20666;
font-weight:500;
}

h3 {
margin-top: 5px;
font-size: 1rem;
margin-bottom: 10px;
color:#f20666;
font-weight:400;
}

h4 {
margin-top: 5px;
font-size: 0.9rem;
margin-bottom: 5px;
color:#f20666;
font-weight:300;
}

h5 {
margin-top: 5px;
font-size: 12px;
margin-bottom: 0px;
color:black;
font-weight:400;
}

a:link, a:active, a:visited {
margin-top:0.5px;
color:#662e9b;
font-size:12px;
font-weight:400;
}

a:hover {
margin-top:0.5px;
color:#662e9b;
font-size:12px;
font-weight:400;
}

/*Defining axis stylings*/

.y-axis text, .x-axis text {
font-family:'Montserrat Alternates', sans-serif;
font-weight:400;
font-size:12px;
opacity:1;
fill:#495867;
}

.x-axis path {
fill:none;
stroke-width:1;
stroke-opacity:1;
stroke:#495867;
}

.y-axis path {
fill:none;
stroke-width:0;
stroke-opacity:1;
stroke:#495867;
}

.y-axis line {
fill:none;
stroke-width:0.8;
stroke-opacity:0.8;
stroke:#662e9b;
stroke-dasharray:2;
}

.x-axis line {
fill:none;
stroke-width:1;
stroke-opacity:0.7;
stroke:#495867;
stroke-dasharray:1;
}

/*Defining test stylings*/

circle {
fill-opacity:0.8;
}

text {
font-family:'Montserrat',sans-serif;
font-size:8px;
font-weight:500;
fill:white;
}


</style>'
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