Published
Edited
Jul 4, 2020
Fork of Untitled
Insert cell
md`# Observable y d3.js`
Insert cell
md`Este notebook explica un ejemplo sencillo que muestra cómo crear una línea de tiempo usando la librería [d3.js](https://d3js.org/).

Esta es una de las principales librerías para realizar visualizaciones de datos y una de las más robustas. A pesar de que es una herramienta relativamente compleja, tiene una amplia documentación y muchos ejemplos que permiten ahorrar esfuerzos y avanzar en su uso y posterior implementación. La documentación de esta librería incluye [una wiki](https://github.com/d3/d3/wiki), [un libro](https://www.imel.ba/edukacija/interactivedatavisualizationfortheweb.pdf) y [una serie de notebooks](https://observablehq.com/collection/@d3/learn-d3) en Observable.

También pueden revisar otras librerias para desarrollar visualizaciones de datos:
- [Vega-Lite](https://observablehq.com/collection/@observablehq/observable-for-vega-lite)
- [Chart.js](https://www.chartjs.org/)
- [Toast UI Chart](https://ui.toast.com/tui-chart/)
- [Timeline.js](https://timeline.knightlab.com/)`
Insert cell
svg`<svg viewBox="0 0 500 100">
<circle id="cir" cx="50" cy="50" r="20" style="fill:rgb(115, 241, 145)"/>
</svg>`
Insert cell
md`---
# Importando ejemplos
D3 puede ser descargada y utilizada localmente. Sin embargo, con la llegada de Observable, una gran cantidad de ejemplos pueden ser encontrados en [la galería](https://observablehq.com/@d3/gallery) de la librería. De esta forma, es posible utilizar la librería sin necesidad de construir las visualizaciones desde 0.`
Insert cell
import { chart as barchart } from "@d3/sortable-bar-chart"
Insert cell
import { data as barchart_data } from "@d3/sortable-bar-chart"
Insert cell
barchart_data
Insert cell
import { chart as forceGraph } from "@d3/disjoint-force-directed-graph"
Insert cell
import { data as forceGraph_data } from "@d3/disjoint-force-directed-graph"
Insert cell
forceGraph_data
Insert cell
import { chart as map } from "@d3/world-choropleth"
Insert cell
import { data as map_data } from "@d3/world-choropleth"
Insert cell
Insert cell
md`---
# Crear una línea de tiempo con d3.js
A pesar de la gran cantidad de ejemplos disponibles en la galería [solo uno](https://observablehq.com/@tezzutezzu/world-history-timeline) hace referencia directa a un timeline *(aunque hay otros ejemplos que de todas formas utilizan datos con una dimensión temporal)*.

Por esta razón (y para explicar conceptos básicos de D3) en este ejercicio se construirá una linea de tiempo básica mediante un script corto que utiliza algunas de las funciones de la librería.

Este ejemplo está construido a partir de [este notebook](https://observablehq.com/@ataylorg/feminist-timeline) creado por [@ataylorg](https://observablehq.com/@ataylorg).`
Insert cell
d3 = require("d3")
Insert cell
Insert cell
datos = d3.csv(
"https://gist.githubusercontent.com/drlztn/191fcab6e1f19a83662a404a9494ca52/raw/e63b309bfdccf7c910f4d6c75ad6287ce0e425aa/fechas.csv",
d => {
return {
// Aquí se realiza una conversión para que cada fila del archivo se muestre correctamente
// 'event' es un string así que no necesita una conversión
// 'date' se debe convertir a un formato de tiempo, en este caso Año(Y)-Mes(m)-Día(d)
// 'year' se puede mantener como un string
event: d.event,
date: d3.timeParse("%Y-%m-%d")(d.raw_date),
year: d.year
};
}
)
Insert cell
md`### Dimensiones del canvas
Las siguientes celdas contienen:
- El ancho de la visualización
- El alto de la viusalización
- Las margenes de canvas`
Insert cell
width = 950
Insert cell
height = 150
Insert cell
margenes = ({ top: 40, left: 30, right: 40, bottom: 80 })
Insert cell
{
/*
Crear un elemento svg en el DOM con un ancho y un alto que corresponden a dos variables.
En este elemento se dibujaran las figuras creadas en el programa (es decir, es el canvas).
https://github.com/observablehq/stdlib/blob/master/README.md#dom
*/
const grafico = d3.select(DOM.svg(width, height));

// En esta variable se alojan los datos
const datos_puntos = datos;

// Aquí se guarda el formato de tiempo que se va a utilizar en los labels de la linea de tiempo
// https://github.com/d3/d3-time-format
const formatoTiempo = d3.timeFormat("%Y");

/*
Aquí se crea el eje horizontal de la línea de tiempo
Los ejes son funciones que crean elementos gráficos que luego se pintarán en el canvas (el elemento 'svg')
Los ejes tienen:
- Un tipo: Se refiere a la orientación del eje (axisTop, axisLeft, axisRight)
- Una escala: el rango de los datos que se muestran en el eje
- Un número de ticks: el número de datos que aparecen en el eje
- El formato de los ticks; el formato en que apareceran los labels de la linea de tiempo
*/
const xAxis = d3
.axisBottom()
.scale(xScale)
.ticks(15)
.tickFormat(formatoTiempo);

/* Tooltip (Si alcanzamos)
// https://github.com/Caged/d3-tip
const tip = d3tooltip()
.attr('class', 'd3-tip')
.html(function(d) {
return d.event;
});
grafico.call(tip);
*/

// El orden en que se dibujan los elementos en D3 es importante. Lo primero que se dibuja estará al fondo y lo último que se dibuja estará al frente.

// Dibujar el eje:
grafico // Selecciona el canvas
.append("g") //Crea un elemento 'g' (un grupo) en donde se dibujará los elementos del eje horizontal
.attr("transform", `translate(0, ${margenes.bottom})`) // Mueve el eje 80px hacia abajo
.call(xAxis); // Dibuja el eje dentro del elemento 'g'

// Dibujar los datos
grafico // Selecciona el canvas
.selectAll("circle") // Selecciona los circulos que pronto van a ser dibujados
.data(datos_puntos) // Cuenta y organiza los datos del dataset
.enter() // Función necesaria para crear nuevos elementos
.append("circle") // Crea un nuevo circulo en el canvas
.attr("cx", d => xScale(d.date))
.attr("cy", 80)
.attr("r", 6)
.attr("fill", color_fill)
.attr("stroke", color_stroke)
.style("stroke-opacity", 1)
.style("fill-opacity", 1);
//.on('mouseover', tip.show)
//.on('mouseout', tip.hide)

// el programa "devuelve" el canvas mediante la función node de D3
return grafico.node();
}
Insert cell
color_fill = "#FF00BF"
Insert cell
color_stroke = "#190707"
Insert cell
md`La siguiente celda define la escala que se quiere para la linea de tiempo. Estas funciones crean una nueva "medida" para un conunto de datos. *domain* se refiere a los datos mínimos y máximos que se quieren escalar. *range* se refiere a los valores a los cuales se quiere escalar esos datos `
Insert cell
xScale = d3
.scaleTime()
.domain([
// Utilizando la función min() y max() de d3, podemos obtener los valores mínimos y máximos de la fecha
d3.min(datos, d => {
return d.date;
}),
d3.max(datos, d => {
return d.date;
})
])
// Para que se escalen al tamaño de la visualización
.range([margenes.left, width - margenes.right])
Insert cell
d3.max(datos, d => {
return d.date;
})
Insert cell
d3.min(datos, d => {
return d.date;
})
Insert cell
d3tooltip = require("d3-tip")
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