Public
Edited
Apr 23
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof color_steps = slider({
min: 0,
max: 30,
step: 1,
value: 10,
title: "Cantidad de colores",
description: "Control para la cantidad de colores a visualizar en la paleta."
})
Insert cell
// Ejemplo, se pueden definir colores mediante HEX, nombre, HSL, RGB/RGBA
swatches(["#ff3399", "hotpink", "hsl(330, 100%, 70.5%)", "rgba(128, 0, 128, 0.2)"])
Insert cell
// Resolución ejercicio a)
Insert cell
html`<div style="display: flex;">
${(
color_steps > 0
? d3.quantize(
d3.scaleLinear()
.domain([0, 0.25, 0.5, 0.75, 1])
.range(["red", "yellow", "green", "blue", "purple"])
.interpolate(d3.interpolateRgb),
color_steps
)
: []
).map(c => html`<div style="background:${c}; width:30px; height:30px;"></div>`)}
</div>`

Insert cell
html`<div style="display: flex;">
${(
color_steps > 0
? d3.quantize(d3.scaleLinear()
.domain([0, 0.5, 1])
.range(["black", "red", "orange"])
.interpolate(d3.interpolateRgb),
color_steps)
: []
).map(c => html`<div style="background:${c}; width:30px; height:30px;"></div>`)}
</div>`

Insert cell
html`<div style="display: flex;">
${(
color_steps > 0
? d3.quantize(
d3.interpolateRgb("#f5f5dc", "#8b4513"),
color_steps
)
: []
).map(c => html`<div style="background:${c}; width:30px; height:30px;"></div>`)}
</div>`

Insert cell
html`<div style="display: flex;">
${(
color_steps > 0
? d3.quantize(
d3.interpolateRgb("blue", "skyblue"),
color_steps
)
: []
).map(c => html`<div style="background:${c}; width:30px; height:30px;"></div>`)}
</div>`

Insert cell
Insert cell
viewof lum_steps = slider({
min: 0,
max: 100,
step: 1,
value: 10,
title: "Luminosidad",
description: "Control para la luminosidad del color."
})
Insert cell
// Resolución ejercicio b


html`<div style="display: flex;">
${(
color_steps > 0
? d3.quantize(d3.interpolateRgb("blue", "skyblue"), color_steps)
: []
).map(c => {
const hsl = d3.hsl(c);
hsl.l = Math.min(1, hsl.l * (lum_steps / 10)); // Ajustamos luminosidad con tu slider
return html`<div style="background:${hsl}; width:30px; height:30px;"></div>`;
})}
</div>`

Insert cell
Insert cell
// Resolución ejercicio c)

iris_raw = await d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/iris.csv")


Insert cell
iris_sin_ancho = iris_raw.map(d => ({
Sepal_Length: +d.Sepal_Length,
Petal_Length: +d.Petal_Length,
Species: d.Species
}))

Insert cell
iris_renombrado = iris_sin_ancho.map(d => ({
longitud_sepalo: d.Sepal_Length,
longitud_petalo: d.Petal_Length,
especie: d.Species
}))

Insert cell
iris_final = iris_raw.map(d => ({
longitud_sepalo: +d.Sepal_Length,
longitud_petalo: +d.Petal_Length,
especie: d.Species,
area_petalo: (+d.Petal_Length * +d.Petal_Width) / 2
}))

Insert cell
Inputs.table(iris_final)
Insert cell
Insert cell
// Resolución ejercicio d)

x = d3.scaleLinear()
.domain(d3.extent(iris_final, d => d.longitud_sepalo))
.range([0, 350])



Insert cell
y = d3.scaleLinear()
.domain(d3.extent(iris_final, d => d.longitud_petalo))
.range([350, 0]) // Invertido para que y crezca hacia arriba
Insert cell
Insert cell
{
// 1. Creación de un área de dibujo (350x350 pixeles).
// Si lo consideran necesario, pueden modificar el tamaño del canvas.
// También es posible que necesiten más de una celda para resolverlo.
const width = 350;
const height = 350;
const margin = {top: 20, right: 20, bottom: 40, left: 40};
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;

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

const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);

// Escalas (reutilizamos las que ya creaste)
const xScale = d3.scaleLinear()
.domain(d3.extent(iris_final, d => d.longitud_sepalo))
.range([0, innerWidth]);

const yScale = d3.scaleLinear()
.domain(d3.extent(iris_final, d => d.longitud_petalo))
.range([innerHeight, 0]);

// Ejes
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));

g.append("g")
.call(d3.axisLeft(yScale));

// Escala de color por especie
const color = d3.scaleOrdinal()
.domain([...new Set(iris_final.map(d => d.especie))])
.range(["#e41a1c", "#377eb8", "#4daf4a"]);

// Círculos
g.selectAll("circle")
.data(iris_final)
.join("circle")
.attr("cx", d => xScale(d.longitud_sepalo))
.attr("cy", d => yScale(d.longitud_petalo))
.attr("r", 4)
.attr("fill", d => color(d.especie))
.attr("opacity", 0.7);

// Retornamos el canvas
return svg.node();
}

Insert cell
Insert cell
{
const width = 350;
const height = 400; // más alto para la leyenda
const margin = {top: 20, right: 20, bottom: 60, left: 40};
const innerWidth = width - margin.left - margin.right;
const innerHeight = 350 - margin.top - margin.bottom;

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

const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);

// Escalas
const xScale = d3.scaleLinear()
.domain(d3.extent(iris_final, d => d.longitud_sepalo))
.range([0, innerWidth]);

const yScale = d3.scaleLinear()
.domain(d3.extent(iris_final, d => d.longitud_petalo))
.range([innerHeight, 0]);

const colorScale = d3.scaleSequential(d3.interpolateYlOrRd)
.domain(d3.extent(iris_final, d => d.area_petalo));

const rScale = d3.scaleSqrt()
.domain(d3.extent(iris_final, d => d.area_petalo))
.range([2, 10]);

// Ejes
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));

g.append("g")
.call(d3.axisLeft(yScale));

// Círculos
g.selectAll("circle")
.data(iris_final)
.join("circle")
.attr("cx", d => xScale(d.longitud_sepalo))
.attr("cy", d => yScale(d.longitud_petalo))
.attr("r", d => rScale(d.area_petalo))
.attr("fill", d => colorScale(d.area_petalo))
.attr("opacity", 0.8);

// Leyenda: gradiente
const defs = svg.append("defs");
const gradient = defs.append("linearGradient")
.attr("id", "legend-gradient")
.attr("x1", "0%")
.attr("x2", "100%");

const legendDomain = d3.extent(iris_final, d => d.area_petalo);
const legendColors = d3.quantize(d3.interpolateYlOrRd, 10);
legendColors.forEach((color, i) => {
gradient.append("stop")
.attr("offset", `${(i / (legendColors.length - 1)) * 100}%`)
.attr("stop-color", color);
});

const legendWidth = 200;
const legendHeight = 10;
const legendX = (width - legendWidth) / 2;
const legendY = 360;

svg.append("rect")
.attr("x", legendX)
.attr("y", legendY)
.attr("width", legendWidth)
.attr("height", legendHeight)
.style("fill", "url(#legend-gradient)");

// Ticks de la leyenda
const legendScale = d3.scaleLinear()
.domain(legendDomain)
.range([legendX, legendX + legendWidth]);

const legendAxis = d3.axisBottom(legendScale)
.ticks(5)
.tickSize(6)
.tickFormat(d3.format(".2f"));

svg.append("g")
.attr("transform", `translate(0,${legendY + legendHeight})`)
.call(legendAxis);

// Título de la leyenda
svg.append("text")
.attr("x", width / 2)
.attr("y", legendY - 5)
.attr("text-anchor", "middle")
.style("font-size", "11px")
.text("Área del pétalo");

return svg.node();
}
Insert cell
Insert cell
Insert cell
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