Public
Edited
Jun 25, 2024
Insert cell
Insert cell
Insert cell
Insert cell
{
// Define SVG
const width = 800;
const height = 300;
const margin = 30;
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Data Preprocessing
const group = d3.group(events, (d) => d["Type"]);

// Scales
const scaleX = d3
.scaleBand()
.domain(Array.from(group).map((d) => d[0]))
.range([margin, width - margin])
.padding(0.1);
const scaleY = d3
.scaleLinear()
.domain([0, d3.max(group, (d) => d[1].length)])
.range([height - margin, margin]);

// Draw Axes
const xAxis = d3.axisBottom(scaleX);
svg
.append("g")
.attr("transform", `translate(0, ${height - margin})`)
.call(xAxis);

const yAxis = d3.axisLeft(scaleY);
svg.append("g").attr("transform", `translate(${margin}, 0)`).call(yAxis);

// Draw Data
svg
.append("g")
.selectAll("rect")
.data(Array.from(group))
.join("rect")
.attr("x", (d) => scaleX(d[0]))
.attr("y", (d) => scaleY(d[1].length))
.attr("width", scaleX.bandwidth())
.attr("height", (d) => scaleY(0) - scaleY(d[1].length))
.attr("fill", "#1eb8d0");

return svg.node();
}
Insert cell
Insert cell
events
X
Start X
Y
Start Y
Color
Team
Size
Facet X
Facet Y
Mark
dot
Type Chart, then Shift-Enter. Ctrl-space for more options.

Insert cell
{
// Define SVG
const width = 800;
const height = 400;
const margin = 30;
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Scales
const scaleX = d3
.scaleLinear()
.domain(d3.extent(events, (d) => d["Start X"]))
.range([margin, width - margin]);

const scaleY = d3
.scaleLinear()
.domain(d3.extent(events, (d) => d["Start Y"]))
.range([height - margin, margin]);

const scaleC = d3
.scaleOrdinal()
.domain(["Home", "Away"])
.range(["orange", "blue"]);

// Draw Axes
const xAxis = d3.axisBottom(scaleX);
svg
.append("g")
.attr("transform", `translate(0, ${height - margin})`)
.call(xAxis);

const yAxis = d3.axisLeft(scaleY);
svg.append("g").attr("transform", `translate(${margin}, 0)`).call(yAxis);

// Draw Data
svg
.append("g")
.selectAll("circle")
.data(events)
.join("circle")
.attr("cx", (d) => scaleX(d["Start X"]))
.attr("cy", (d) => scaleY(d["Start Y"]))
.attr("r", 3)
.attr("fill", "none")
.attr("stroke", (d) => scaleC(d["Team"]));

return svg.node();
}
Insert cell
Insert cell
{
// Define SVG
const width = 800;
const height = 400;
const margin = 30;
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Scales
const scaleX = d3
.scaleTime()
.domain(d3.extent(aapl, (d) => d["Date"]))
.range([margin, width - margin]);

const scaleY = d3
.scaleLinear()
.domain([0, d3.max(aapl, (d) => d["Close"])])
.range([height - margin, margin]);

// Draw Axes
const xAxis = d3.axisBottom(scaleX);
svg
.append("g")
.attr("transform", `translate(0, ${height - margin})`)
.call(xAxis);

const yAxis = d3.axisLeft(scaleY);
svg.append("g").attr("transform", `translate(${margin}, 0)`).call(yAxis);

// Draw Data
svg
.append("g")
.append("path")
.datum(aapl)
.attr(
"d",
d3
.line()
.x((d) => scaleX(d["Date"]))
.y((d) => scaleY(d["Close"]))
)
.attr("stroke", "black")
.attr("fill", "none");

return svg.node();
}
Insert cell
{
// Define SVG
const width = 800;
const height = 400;
const margin = 30;
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Scales
const scaleX = d3
.scaleBand()
.domain(d3.range(1, 32))
.range([margin, width - margin])
.padding(0.02);

const scaleY = d3
.scaleBand()
.domain(d3.range(0, 12))
.range([margin, height - margin])
.padding(0.02);

const scaleC = d3
.scaleLinear()
.domain(d3.extent(weather, (d) => d.temp_max))
.range(["blue", "red"]);

// Draw Axes
const xAxis = d3.axisBottom(scaleX);
svg
.append("g")
.attr("transform", `translate(0, ${height - margin})`)
.call(xAxis);

const yAxis = d3.axisLeft(scaleY);
svg.append("g").attr("transform", `translate(${margin}, 0)`).call(yAxis);

// Draw Data
svg
.append("g")
.selectAll("rect")
.data(weather.slice(-365))
.join("rect")
.attr("x", (d) => scaleX(d.date.getUTCDate()))
.attr("y", (d) => scaleY(d.date.getUTCMonth()))
.attr("width", scaleX.bandwidth())
.attr("height", scaleY.bandwidth())
.attr("opacity", 0.8)
.attr("fill", (d) => scaleC(d.temp_max));

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
import { Tooltip } from "@gshirato/chart-class"
Insert cell
{
// Define SVG
const width = 800;
const height = 300;
const margin = 30;
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Creae histogram
const histogram = d3
.histogram()
.value(function (d) {
return d["weight (lb)"];
}) // I need to give the vector of value
.domain([1500, 5500]) // then the domain of the graphic
.thresholds(d3.range(1500, 5500, 500)); // then the numbers of bins

const bins = histogram(cars);

// Scale X
const scaleX = d3
.scaleBand()
.domain(bins.map((d) => d.x0))
.range([margin, width - margin])
.padding(0.02);

// Scale Y
const scaleY = d3
.scaleLinear()
.domain([0, d3.max(bins, (d) => d.length)])
.range([height - margin, margin]);

// Draw Axes
const xAxis = d3.axisBottom(scaleX);
svg
.append("g")
.attr("transform", `translate(0, ${height - margin})`)
.call(xAxis)
.selectAll("text")
.text((d) => `${d}~${d + 500}`);

const yAxis = d3.axisLeft(scaleY);
svg.append("g").attr("transform", `translate(${margin}, 0)`).call(yAxis);

// Set Tooltip
const tooltip = new Tooltip();

// Draw Data
svg
.append("g")
.selectAll("rect")
.data(bins)
.join("rect")
.attr("x", (d) => scaleX(d.x0))
.attr("y", (d) => scaleY(d.length))
.attr("width", scaleX.bandwidth())
.attr("height", (d) => scaleY(0) - scaleY(d.length))
.attr("fill", "#1eb8d0")
.on("mouseover", function (event, d) {
tooltip.show(event, d);
})
.on("mousemove", function (event, d) {
tooltip.setText(
`<b>weight (lb)</b> ${d.x0}~${d.x1} <br><b>frequency</b> ${d.length}`
);
tooltip.move(event, d);
})
.on("mouseleave", function (event, d) {
tooltip.hide(event, d);
});

return svg.node();
}
Insert cell
Insert cell
soccer = require("d3-soccer")
Insert cell
function getIds(tracking) {
const res = Object.keys(tracking[0])
.filter((d) => d.slice(-2) == "_d")
.map((d) => d.split("_").slice(0, 2).join("_"))
.sort((a, b) => d3.ascending(+a.split("_")[1], b.split("_")[1]));

res.push("ball");

return res;
}
Insert cell
ids = getIds(tracking_1)
Insert cell
Insert cell
Insert cell
{
// Define SVG
const width = 800;
const height = 300;
const margin = 30;
const svg = d3.create("svg").attr("width", width).attr("height", height);

const pitch = soccer
.pitch()
.height(height)
.rotate(false)
.clip([
[0, 0],
[105, 68]
]);

// Scales
const scaleX = d3.scaleLinear().domain([0, 1]).range([0, 105]);
const scaleY = d3.scaleLinear().domain([0, 1]).range([0, 68]);
const scaleC = d3
.scaleOrdinal()
.domain(["home", "away"])
.range(["orange", "blue"])
.unknown("red");

// Draw Pitch
svg.append("g").call(pitch);

// Filter data (use a snapshot)
const snapshot = tracking.filter((d) => d.frame_id === frame);

// Draw Data
const layer = svg.select("#above");
layer
.append("g")
.selectAll("circle")
.data(snapshot)
.join("circle")
.attr("class", (d) => `id-${d.id}`)
.attr("debug", (d) => console.log("debug:", d))
.attr("cx", (d) => scaleX(d.x))
.attr("cy", (d) => scaleY(d.y))
.attr("r", (d) => (d.team === "ball" ? 0.4 : 0.8))
.attr("fill", "none")
.attr("stroke-width", 0.3)
.attr("stroke", (d) => scaleC(d.team))
.on("mouseover", mouseover);

// Add Voronoi Selection
const delaunay = d3.Delaunay.from(
snapshot
.filter((d) => d.id !== "ball")
.map((d) => [scaleX(d.x), scaleY(d.y)])
);
const voronoi = delaunay.voronoi([0, 0, 105, 68]);

layer
.append("g")
.attr("class", "voronoi")
.selectAll("path")
.data(snapshot)
.join("path")
.attr("class", (d) => `id-${d.id}`)
.attr("d", (_, i) => voronoi.renderCell(i))
.attr("fill", "none")
.attr("stroke", showVoronoi ? "black" : "none")
.attr("stroke-width", 0.3)
.attr("opacity", 0.8)
.attr("stroke-dasharray", "1,2")
.attr("pointer-events", "all")
.on("mouseover", mouseover)
// .on("mousemove", mouseover)
.on("mouseleave", mouseleave);

function mouseover(event, d) {
const className = d3.select(this).attr("class");

d3.select(`.${className}`).attr("stroke-width", 1);
}

function mouseleave(event, d) {
const className = d3.select(this).attr("class");
d3.select(`.${className}`).attr("stroke-width", 0.3);
}

return svg.node();
}
Insert cell
eval("[]")
Insert cell
function convert(tracking, ids) {
const res = [];
for (const row of tracking) {
const data = {};
for (const column of ["period_id", "frame_id"]) {
data[column] = row[column];
}
for (const id of ids) {
if (row[`${id}_x`] === "" && id !== "ball") continue;
res.push({
...data,
id: id,
team: id.split("_")[0],
number: +id.split("_")[1],
x: row[`${id}_x`],
y: row[`${id}_y`]
});
}
}
return res;
}
Insert cell
tracking = convert(tracking_1, ids)
Insert cell
Insert cell
Insert cell
Sample_Game_2_RawEventsData.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Sample_Game_2_RawTrackingData_1st.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Sample_Game_2_RawTrackingData_2nd.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
import {Sunburst} from "@d3/sunburst"
Insert cell
xCoordsGlobal = []
Insert cell
ycoords = []
Insert cell
data1 = [0, 100, 200]
Insert cell
data2 = [50, 150, 250]
Insert cell
exampleData = [data1, data2]
Insert cell
names = ["data 1", "data 2"]
Insert cell
Insert cell
Insert cell
draw()
Insert cell
function draw() {
d3.select("#example").selectAll("*").remove();
const svg = d3.select("#example").append("svg");

svg.attr("height", 300).attr("width", 300);

svg
.append("g")
.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", (d) => d)
.attr("cx", (d) => d)
.attr("cy", (d) => d)
.attr("r", 10)
.attr("fill", "black");
}
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