Public
Edited
Feb 9
Insert cell
Insert cell
Insert cell
raw = FileAttachment("iris.csv").csv()
Insert cell
function createAxis(scale, orientation, transform) {
return g => g.attr("transform", transform).call(orientation(scale));
}
Insert cell
function createLegend(svg, x_position, data, color, config) {
const legend = svg.selectAll(".legend")
.data(data)
.enter()
.append("g")
.attr("class", "legend")
.attr("transform", (d, i) => `translate(0, ${config.margin.top + i * (config.rectHeight + config.verticalPadding)})`);

legend.append("rect")
//.attr("x", config.width - config.margin.right - config.rectWidth)
.attr("x", x_position)
.attr("y", 0)
.attr("width", config.rectWidth)
.attr("height", config.rectHeight)
.style("fill", d => color(d));

legend.append("text")
//.attr("x", config.width - config.margin.right - config.rectWidth - config.horizontalPadding)
.attr("x", x_position - config.horizontalPadding)
.attr("y", config.rectHeight / 2)
.attr("dy", "0.35em")
.text(d => d)
.attr("text-anchor", "end");
}
Insert cell
function scatterPlot (data, x_value, y_value, color_value)
{
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 30, left: 50 };

const legendRectWidth = 10
const legendRectHeight = 10
const legendXPosition = width - margin.right - legendRectWidth
const legendVerticalPadding = 10
const legendHorizontalPadding = 15
const yAxisTextVerticalPadding = 45
const xAxisTextVerticalPadding = 10
const axisTextHorizontalPadding = 35

const color = d3.scaleOrdinal(d3.schemeCategory10)

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);

const scaleX = d3.scaleLinear()
.domain([0, d3.max(data, d => d[x_value])])
.range([margin.left, width - margin.right]);
const scaleY = d3.scaleLinear()
.domain([0, d3.max(data, d => d[y_value])])
.range([margin.top, height - margin.bottom]);
//.range([height - margin.bottom, margin.top]);

svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", (d, i) => scaleX(d[x_value]))
.attr("cy", (d, i) => scaleY(d[y_value]))
.attr("r", 5)
.style("fill", d => color(d[color_value]))

const xAxis = createAxis(scaleX, d3.axisBottom, `translate(0, ${height - margin.bottom})`)
svg.append("g")
.call(xAxis);

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

const colors_values = new Set(data.map(d => d[color_value]))

createLegend(svg, legendXPosition, colors_values, color, {
width,
margin,
rectWidth: legendRectWidth,
rectHeight: legendRectHeight,
verticalPadding: legendVerticalPadding,
horizontalPadding: legendHorizontalPadding,
});

svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top + yAxisTextVerticalPadding)
.attr("transform", `rotate(-90, ${margin.left - axisTextHorizontalPadding}, ${margin.top + yAxisTextVerticalPadding})`)
.text(y_value)
.attr("text-anchor", "end")
.style("font-size", "13px");

svg.append("text")
.attr("x", width - margin.right - axisTextHorizontalPadding)
.attr("y", height - margin.bottom - xAxisTextVerticalPadding)
.text(x_value)
.attr("text-anchor", "end")
.style("font-size", "13px");

return svg.node()
}
Insert cell
scatterPlot(raw, "sepal_length", "sepal_width", "species")
Insert cell
Insert cell
stocks = FileAttachment("stocks.csv").csv()
Insert cell
stock_parsed = stocks.map(d => {
let r = {}
r.symbol = d.symbol
r.date = new Date(d.date)
r.price = +d.price

return r
})
Insert cell
function lineChart (data, x_value, y_value, color_value)
{
const margin = ({top: 20, right: 30, bottom: 30, left: 40})
const height = 500
const legendRectWidth = 10
const legendRectHeight = 10
const legendXPosition = margin.left +100
const legendVerticalPadding = 10
const legendHorizontalPadding = 15
const yAxisTextVerticalPadding = 45
const xAxisTextVerticalPadding = 10
const axisTextHorizontalPadding = 35

const x = d3.scaleTime()
.domain(d3.extent(stock_parsed, d=> d.date))
.range([margin.left, width - margin.right])
const y = d3.scaleLinear()
.domain(d3.extent(stock_parsed, d=> d.price))
.range([height - margin.bottom, margin.top])
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

const color = d3.scaleOrdinal(d3.schemeCategory10)

const grouped_data = d3.group(stock_parsed, d => d.symbol)
const line = d3.line()
.x(d => x(d.date))
.y(d => y(d.price))
svg.selectAll("path").data(grouped_data).enter().append("path")
.attr("d", d => line(d[1]))
.attr("stroke", d => color(d[0]))
.attr("fill", "none")


const xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x))

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

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

const colors_values = new Set(data.map(d => d[color_value]))

createLegend(svg, legendXPosition, colors_values, color, {
width,
margin,
rectWidth: legendRectWidth,
rectHeight: legendRectHeight,
verticalPadding: legendVerticalPadding,
horizontalPadding: legendHorizontalPadding,
});

svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top + yAxisTextVerticalPadding)
.attr("transform", `rotate(-90, ${margin.left - axisTextHorizontalPadding}, ${margin.top + yAxisTextVerticalPadding})`)
.text(y_value)
.attr("text-anchor", "end")
.style("font-size", "13px");

svg.append("text")
.attr("x", width - margin.right - axisTextHorizontalPadding)
.attr("y", height - margin.bottom - xAxisTextVerticalPadding)
.text(x_value)
.attr("text-anchor", "end")
.style("font-size", "13px");

return svg.node();
}
Insert cell
lineChart(stock_parsed, "date", "price", "symbol")
Insert cell
Insert cell
dataset = Array.from({length: 20000}, d3.randomNormal(1, 1))
Insert cell
function histogram (data)
{
const margin = ({top: 20, right: 30, bottom: 30, left: 40})
const height = 500

const x = d3.scaleLinear()
.domain(d3.extent(data))
.range([margin.left, width - margin.right])

const bins = d3.bin()(data)
const y = d3.scaleLinear()
.domain([0, d3.max(bins, d => d.length)])
.range([height - margin.bottom, margin.top])

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

svg.selectAll("rect").data(bins).enter().append("rect")
.attr("x", (d, i) => x(d.x0))
.attr("y", d => y(d.length) - margin.bottom)
.attr("width", (d, i) => 30)
.attr("height", d => height - y(d.length))

const xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x))

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

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

return svg.node();
}
Insert cell
histogram(dataset)
Insert cell
Insert cell
data_viz_draft = FileAttachment("data_viz_draft.jpg").image()
Insert cell
captureDecran20250202A225353 = FileAttachment("Capture d’écran 2025-02-02 à 22.53.53.png").image()
Insert cell
captureDecran20250202A222937 = FileAttachment("Capture d’écran 2025-02-02 à 22.29.37.png").image()
Insert cell
antartic = FileAttachment("antartic.png").image()
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