Public
Edited
Jun 17, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Necesitamos combinar todo en una función IIFE
(async () => {
// Configuración de tamaño y margen
const margin = { top: 30, right: 30, bottom: 30, left: 30 };
const width = 900;
const height = 500;

// Escalas y ejes
const xScale = d3
.scaleLinear()
.rangeRound([margin.left, width - margin.right]);
const yScale = d3
.scaleBand()
.rangeRound([height - margin.bottom, margin.top]);
const colorScale = d3.scaleOrdinal(d3.schemeTableau10);
const xAxis = (g) =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(xScale).ticks(width / 80))
.call((g) => g.select(".domain").remove());
const yAxis = (g) =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(yScale).tickSizeOuter(0))
.call((g) => g.select(".domain").remove());

// Definición de clase de Tooltip
class Tooltip {
constructor() {
this.tooltip = d3
.select("body")
.append("div")
.attr("class", "d3-tip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden");
}

show(event, d) {
const total = d3.sum(d.Estado, (s) => s.Hecho);
this.tooltip
.html(
`<strong>Departamento:</strong> <span style='color:red'>${d.Departamento}</span> <br> <strong>Total:</strong> <span style='color:red'>${total}</span>`
)
.style("top", event.pageY - 10 + "px")
.style("left", event.pageX + 10 + "px")
.style("visibility", "visible");
}

hide() {
this.tooltip.style("visibility", "hidden");
}
}

// Preparar los datos para la visualización
const data = await d3.csv(
"https://docs.google.com/spreadsheets/d/e/2PACX-1vRTWPjGdlmWMWsLs3ltdBkKLmWEIiTB_uHqZCucFFot7tThzyyVMqWPAKkcLaoDSPinuMFPErC5kkDG/pub?output=csv"
);

const processedData = d3.rollups(
data,
(v) => d3.sum(v, (leaf) => +leaf.Hecho),
(d) => d.Departamento,
(d) => d.Estado
);

let graphData = processedData.map(([dep, stats]) => ({
Departamento: dep,
Estado: stats.map(([Estado, Hecho]) => ({ Estado, Hecho }))
}));

// Ajuste las escalas de acuerdo con los datos
xScale.domain([
0,
d3.max(graphData, (d) => d3.sum(d.Departamento, (s) => s.Hecho))
]);
yScale.domain(graphData.map((d) => d.Departamento));
colorScale.domain(data.map((d) => d.Estado));

// Generar el gráfico
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

const tooltip = new Tooltip();

svg
.selectAll("g.Estado")
.data(graphData)
.join("g")
.attr("class", "Estado")
.selectAll("rect")
.data((d) => d.Estado)
.join("rect")
.attr("fill", (d) => colorScale(d.Estado))
.attr("x", (d) => xScale(0))
.attr("y", (d) => yScale(d.dep))
.attr("width", (d) => xScale(d.Hecho))
.attr("height", yScale.bandwidth())
.on("mouseover", (event, d) => tooltip.show(event, d))
.on("mouseout", () => tooltip.hide());

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

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

// Generar la leyenda
const legend = svg
.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(colorScale.domain().slice().reverse())
.join("g")
.attr("transform", (d, i) => `translate(-50,${i * 20})`);

legend
.append("rect")
.attr("x", width - 19)
.attr("width", 19)
.attr("height", 19)
.attr("fill", colorScale);

legend
.append("text")
.attr("x", width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text((d) => d);

return svg.node();
})()
Insert cell
Insert cell
data.length
Insert cell
Insert cell
data.columns
Insert cell
Insert cell
Insert cell
Insert cell
// Creamos el gráfico de barras
Plot.plot({
marginLeft: 200,
y: {
label: "Departamento",
domain: dataForPlot.map((d) => d.key)
},
x: {
label: "Suma de Hecho",
grid: true
},
marks: [
Plot.barX(dataForPlot, {
x: "value",
y: "key",
title: (d) => `Suma de Hecho: ${d.value}` // Configuramos el tooltip para mostrar la suma de "Hecho"
})
]
})
Insert cell
// Convertimos la columna 'Hecho' a tipo numérico
data.forEach((d) => (d.Hecho = +d.Hecho))
Insert cell
Insert cell
// Se extraen los primeros 10 elementos de la tabla y se guardan en una variable

top10 = data.slice(0,10)
Insert cell
// Se extraen los primeros 100 elementos de la tabla y se guardan en una variable

top100 = data.slice(0,100)
Insert cell
Insert cell
// Creamos el arreglo en donde ponemos objetos con una propiedad con los datos y otra propiedad con el nombre que queremos que salga en nuestro menu

arreglo_datos = [
{data: data, nombre: "Completos"},
{data: top100, nombre: "Top 100"},
{data: top10, nombre: "Top 10"}
]
Insert cell
Insert cell
viewof seleccionados_tabla = Inputs.table(datos_seleccionados_tabla[0].data)
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
// Aumentamos el margen izquierdo para que los nombres de los departamentos se lean adecuadamente
marginLeft: 200,

// Configuramos el eje Y con el nombre de los departamentos
y: {
label: "Departamento donde ocurre la desaparición DANE",
domain: sortedCounts.map((d) => d.key),
grid: true
},

// Configuramos el eje X con el recuento de las desapariciones, y añadimos una grilla
x: {
label: "Número de desapariciones",
grid: false
},

// Agregamos una marca de barra en Y para representar el recuento de desapariciones
marks: [
Plot.dot(sortedCounts, {
x: "value",
y: "key"
})
]
})
Insert cell
Insert cell
Insert cell
// viewof columna_venta = Inputs.select(columnas_ventas, {label: "Selecciona un tipo de venta"})
Insert cell
Insert cell
Plot.plot({
// Para que los nombres se puedan leer, le ponemos una margen a la izquierda
marginLeft: 200,

// Le damos algunas propiedades a nuestro eje Y: un nombre y un orden
y: {
label: "Nombre del juego",

// usamos d3.sort para definir un orden que sea por las ventas globales
domain: d3
.sort(sortedCounts, (d) => -d[columna_venta])
.map((d) => d["Departamento donde ocurre la desaparición DANE"])
},

// Le ponemos un label a nuestro eje X y le añadimos una grilla
x: {
label: "Ventas globales (en millones)",
grid: true
},

// Agregamos una marca y se la asignamos al atributo columna_venta
marks: [
Plot.barX(sortedCounts, {
x: columna_venta,
y: "Departamento donde ocurre la desaparición DANE"
})
]
})
Insert cell
Insert cell
Insert cell
// creamos nuestro arreglo con el nombre de las columnas como objetos para poder cambiar la leyenda.

columnas_ventas_obj = [
{
columna: "NA_Sales",
nombre: "Ventas en Norte América"
},
{
columna: "EU_Sales",
nombre: "Ventas en Europa"
},
{
columna: "JP_Sales",
nombre: "Ventas en Japón"
},
{
columna: "Other_Sales",
nombre: "Otras ventas"
},
{
columna: "Global_Sales",
nombre: "Ventas globales"
}
]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
// Le asigno un tamaño a la gráfica
width: (width - 40),
height: 600,

// Para que los nombres se puedan leer, le ponemos una margen a la izquierda y abajo
marginLeft:250,
marginBottom:50,

// Le asigno unos estilos
style: {
// Sangría
padding: 20,
// Color de fondo
backgroundColor: color_fondo,
// Color de las letras
color: color_letras,
// Tamaño de la letra
fontSize: 14,
// Fuente de la letra
fontFamily: 'monospace'
},

// Le damos algunas propiedades a nuestro eje Y: un nombre y un orden
y:{
label: "Nombre del juego",

// usamos d3.sort para definir un orden que sea por las ventas globales
domain: d3.sort(top10, d => -d[columna_venta_obj[0].columna]).map(d => d['Name'])
},

// Le ponemos un label a nuestro eje X y le añadimos una grilla
x: {
label: columna_venta_obj[0].nombre + " (en millones)",
grid: true,

// Le asignamos un dominio fijo al eje X para que cuando cambiemos de columna la escala se mantenga
domain: [0, 90]
},

// Agregamos una marca y se la asignamos al atributo columna_venta
marks: [
Plot.barX(top10, {x: columna_venta_obj[0].columna, y: "Name", fill: color_uno})
]
})
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