Un taller de d3.js difícil y divertido*
¿qué necesitas para hacer visualizaciones
de datos impresionantes?
*http://www.macwright.org/presentations/dcjq/
Javier Abadía
@javierabadia
¿por qué es difícil?
¿y por qué es divertido?
Codemotion 2016 - d3.js un taller divertido y difícil
un gráfico de barras
nop!
de cabeza!
http://bl.ocks.org/mbostock/4062006
logística
• ¿os funciona todo?
• https://github.com/jabadia/d3-workshop
¿qué queremos conseguir?
1. preparar los datos
2. elegir el tipo de visualización apropiado
3. buscar un ejemplo (p.ej. en bl.ocks.org) parecido
4. cambiar los datos
5. cambiar la apariencia
6. adaptar la interacción
7. integrarlo en mi app
contar una historia
con los datos
al lío…
Un poco de teoría
d3.js, Javascript Nivel Demonio+
d3.js
• no es una herramienta de visualización
– Tableau, Excel, R-studio
• no es una librería de gráficas
– highcharts.js, google charts, dimple, nvd3
• no es una librería de mapas
– leaflet.js
• no es una librería de dibujo
– SVG, Canvas
entonces, que es?
Data
Driven
Documents
D
D
D
3
¿qué tiene de especial?
DATOS
JSONCSV
TSV …
d3 necesita JS nivel Demonio+
Codemotion 2016 - d3.js un taller divertido y difícil
funciones
http://www.smashingmagazine.com/2014/07/dont-be-scared-of-functional-programming/
function aceptaDos(a, b)
{
a = a || ‘default A’; 🌶
b = b || ‘default B’;
return a + b + arguments[2];
}
aceptaDos(); // legal
aceptaDos(‘pA’); // legal
aceptaDos(‘pA’,’pB’); // legal
aceptaDos(‘pA’,’pB’,’pC’); // legal
function modifica1(s)
{
return 'un ' + s + ' precioso';
}
function modifica2(s)
{
return 'el mejor ' + s + ' de todos';
}
function generaDia(m)
{
return m('dia');
}
generaDia(modifica1); // ‘un dia precioso’
generaDia(modifica2); // ‘el mejor dia de todos’
function modifyString()
{
var prefix='|';
var postfix='|';
var output = function(s)
{
return prefix + s + postfix;
}
output.prefix = function(p) { prefix = p; return output; }
output.postfix = function(p) { postfix = p; return output; }
return output;
}
m = modifyString().prefix(‘un’).postfix(‘precioso’);
m(‘dia’) // ‘un dia precioso’
❶
❷
❸
❹
❶ ❷ ❹
e.attr('x', function(d) { return x(d); })
e.attr('x', x)
e.attr('x', function(d) { return this.x(d); })=>=>
¿lo tenéis?
¿quien sabe jQuery?
selecciones
lis = $(‘li’)
lis.length
lis.each( function() { console.log(this); } )
lis.each( function() {$(this).fadeOut(); } ) 🌶
lis.each( function() {$(this).fadeIn(); } ) 🌶
lis.fadeOut()
lis.fadeIn()
lis.css({color: ‘red’})
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul>
más selecciones
• jQuery
– $(‘li’).css(‘background-color’,’red’);
• D3
– d3.selectAll(‘.bar’).attr(‘fill’,’red’);
• pero…
– d3.selectAll(‘.bar’).data(meses);
los joins
<ul>
<li>Java</li>
<li>C</li>
<li>C++</li>
<li>C#</li>
<li>Python</li>
<li>JavaScript</li>
<li>Visual Basic .NET</li>
<li>Perl</li>
<li>Objective-C</li>
<li>Assembly language</li>
<li>Swift</li>
<li>Ruby</li>
<li>Visual Basic</li>
<li>Delphi/Object Pascal</li>
<li>Go</li>
<li>Groovy</li>
<li>R</li>
<li>MATLAB</li>
<li>PL/SQL</li>
</ul>
var progLang = [
'Java',
'C',
'C++',
'C#',
'Python',
'JavaScript',
'PHP',
'Visual Basic .NET',
'Perl',
'Objective-C',
'Assembly language',
'Swift',
'Ruby',
'Visual Basic',
'Delphi/Object Pascal',
'Go',
'Groovy',
'R',
'MATLAB',
'PL/SQL',
];
var progLang = [ 'Java', …, 'PL/SQL'];
var list = d3.select('ul');
var items = list.selectAll('li.lang').data(progLang);
items.enter().append('li')
.attr('class', 'lang')
.text(String);
…
.text(function(d) { return String(d); });
❶
❸❷
❹
❺
❻
selection
.attr(‘x’, function(d, i) { … })
.text(function(d, i) { … })
.property(‘selected’, function(d, i) { … })
.style(‘opacity’, function(d, i) { … })
this.__data__
function(d,i,data) { … }
d = dato
i = índice del dato
data = array de todos los datos
this = nodo DOM
al lío
Más teoría
Visualización de datos, codificación visual
valores
codificación
visual
https://www.safaribooksonline.com/library/view/designing-data-visualizations/9781449314774/
var x = d3.scaleLinear()
.domain([10, 130])
.range([0, 960]);
x(20); // 80
x(50); // 320
var color = d3.scaleLinear()
.domain([10, 100])
.range(["brown", "steelblue"]);
color(20); // "#9a3439"
color(50); // "#7b5167"
var x = d3.scaleTime()
.domain([new Date(2000, 0, 1), new Date(2000, 0, 2)])
.range([0, 960]);
x(new Date(2000, 0, 1, 5)); // 200
x(new Date(2000, 0, 1, 16)); // 640
x.invert(200); // Sat Jan 01 2000 05:00:00 GMT-0800 (PST)
x.invert(640); // Sat Jan 01 2000 16:00:00 GMT-0800 (PST)
var x = d3.scalePoint()
.domain(["a", "b", "c"])
.range([0, width]);
var x = d3.scaleBand()
.domain(["a", "b", "c"])
.range([0, width])
.padding(0.05);
var c = d3.scaleOrdinal()
.domain(["apple", "orange", "banana", "grapefruit"])
.range(["green”, ”orange”, ”yellow”, ”red"]);
ahora si que no
os libráis de las barras
Datos dinámicos y movimiento
Animación, actualización de datos, story-telling
[
'Python',
'JavaScript',
'PHP',
'Visual Basic .NET',
'Perl',
'Objective-C',
'Assembly language',
'Swift',
'Ruby',
'Visual Basic',
'Delphi/Object Pascal',
'Go',
'Groovy',
'R',
'MATLAB',
'PL/SQL',
]
<ul>
<li>Java</li>
<li>C</li>
<li>C++</li>
<li>C#</li>
<li>Python</li>
<li>JavaScript</li>
<li>Visual Basic .NET</li>
<li>Perl</li>
<li>Objective-C</li>
<li>Assembly language</li>
<li>Swift</li>
<li>Ruby</li>
<li>Visual Basic</li>
<li>Delphi/Object Pascal</li>
<li>Go</li>
</ul>
EXIT
UPDATE
UPDATE
ENTER
Codemotion 2016 - d3.js un taller divertido y difícil
var bars = svg.selectAll('rect.bar').data(visibleWeather, day);
console.log(bars.enter().size(), bars.size(), bars.exit().size());
bars.enter() // ENTER
.append('rect')
.attr('class','bar')
.attr('x', function(d,i) { return x(i) + x.bandwidth(); })
.attr('width', x.bandwidth())
.attr('y', function(d) { return y(tempMin(d)); })
.attr('height', function(d) { return y(tempMax(d)-tempMin(d)); })
.style('fill', function(d) { return color(tempMin(d));})
.transition()
.attr('x', function(d,i) { return x(i); })
bars // UPDATE
.transition()
.attr('x', function(d,i) { return x(i); })
.attr('width', x.bandwidth())
.attr('y', function(d) { return y(tempMin(d)); })
.attr('height', function(d) { return y(tempMax(d)-tempMin(d)); })
bars.exit() // EXIT
.remove()
Codemotion 2016 - d3.js un taller divertido y difícil
going out of the box
layouts, arcs, paths
layouts
• Bundle
• Chord
• Cluster
• Force
• Histogram
• Pack
• Partition
• Pie
• Stack
• Tree
• Treemap
• …
datos
datos más
fáciles de pintar
{
region: ‘Norte’,
ventas: 11245
}
{
startAngle: 0,
endAngle: 0.124,
data: {
region: ‘Norte’,
ventas: 11245
}
}
data
pie(data)
arc
• d3.arc() es una función que devuelve un generador de arcos
– un arco es un path de SVG
• se puede/suele configurar con parámetros fijos
var arc = d3.arc();
arc({
innerRadius: 0,
outerRadius: 100,
startAngle: 0,
endAngle: Math.PI / 2
});
// "M0,-100A100,100,0,0,1,100,0L0,0Z"
var arc = d3.arc()
.innerRadius(0)
.outerRadius(100)
.startAngle(0)
.endAngle(Math.PI / 2);
arc();
// "M0,-100A100,100,0,0,1,100,0L0,0Z"
pie y arc trabajan juntos
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var g = svg.selectAll(".arc").data(pie(countries))
.enter().append("path")
.attr("class", "arc")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); });
la mitad de los parámetros
la otra mitad
WTF?
http://bl.ocks.org/mbostock/3887235
¡dale manolo!
tu propio layout
var resultados = [
{sCandidatura: ’pp', iEscanos: 23 },
{sCandidatura: ’psoe', iEscanos: 20 },
{sCandidatura: ’podemos', iEscanos: 11 },
{sCandidatura: ’ciudadanos', iEscanos: 7 },
];
nos preparamos los datos
var resultados = [
{sCandidatura: ’pp', iEscanos: 23 },
{sCandidatura: ’psoe', iEscanos: 20 },
{sCandidatura: ’podemos', iEscanos: 11 },
{sCandidatura: ’ciudadanos', iEscanos: 7 },
];
var diputados = [
’pp0’, ‘pp1’, ’pp2’, …, ’pp22’,
‘psoe0’, ’psoe1’, …,’psoe19’,
’podemos0’, …,
…, ’ciudadanos6’
];
mi layout
var squaresLayout = function(squaresPerRow, width, gapRatio)
{
var squareSize = width / (squaresPerRow + (squaresPerRow-1) * gapRatio);
var gapSize = squareSize * gapRatio;
var layout = function(data)
{
return _.map(data, function(d, i)
{
var row = Math.floor(i / squaresPerRow);
var col = i - (row*squaresPerRow);
return {
row: row,
col: col,
x: col * squareSize + col * gapSize,
y: row * squareSize + row * gapSize,
data: d,
};
});
}
layout.squareSize = squareSize;
layout.gapSize = gapSize;
layout.squaresPerRow = squaresPerRow;
return layout;
};
layout = squaresLayout(escanosPorFila, width, gapRatio);
var squares = svg.select('.squares').datum(diputados)
.selectAll('rect.square').data(layout, function(d) {
return d.data.idDiputado;
});
WTF?
Codemotion 2016 - d3.js un taller divertido y difícil
story-telling
elegir el layout, animaciones
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
http://www.datamake.io/project/film-money
Codemotion 2016 - d3.js un taller divertido y difícil
crossfilter - dc.js
http://square.github.io/crossfilter/
https://dc-js.github.io/dc.js/
d3.js v3 ▶v4
no toques… ¿por que tocas?
librería modular
v3
<script src="https://d3js.org/d3.v3.js"></script>
v4
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
<script src="https://d3js.org/d3-scale.v1.min.js"></script>
cambios de nombres
v3
d3.scale.linear
d3.layout.treemap
d3.scale.ordinal
d3.time.format
v4
d3.scaleLinear
d3.treemap
d3.scaleOrdinal
d3.scaleBands
d3.scalePoints
d3.timeFormat
cambian los joins
v3 v4
var circle = svg.selectAll("circle").data(data) // UPDATE
.style("fill", "blue");
// ENTER; modifies UPDATE! 🌶
circle.enter().append("circle")
.style("fill", "green");
circle // ENTER + UPDATE
.style("stroke", "black");
circle.exit().remove(); // EXIT
var circle = svg.selectAll("circle").data(data) // UPDATE
.style("fill", "blue");
circle.enter().append("circle") // ENTER
.style("fill", "green")
.merge(circle) // ENTER + UPDATE
.style("stroke", "black");
circle.exit().remove(); // EXIT
otros cambios
• mejor soporte para Canvas (d3-shape)
• transiciones coordinadas
• muchos otros cambios menores
– https://iros.github.io/d3-v4-whats-new
integración
en mis apps
la convención de márgenes
var margin = {top: 20, right: 10, bottom: 20, left: 10};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
http://bl.ocks.org/mbostock/3019563
var x = d3.scale.linear()
.range([0, width]); // area útil
var y = d3.scale.linear()
.range([height, 0]); // area útil
angular.js - directivas
<div class="participacion"
an-chart-participacion
data-current='dataCurrent'
data-prev='dataPrev'>
</div>
angular.js - directivas
module.directive('anChartParticipacion', function()
{
var _drawChart = function(elem, dataCurrent, dataPrev, options)
{
… // codigo d3 aquí …
};
return {
restrict: 'A',
scope: {
dataCurrent: '=current',
dataPrev: '=prev',
},
link: function(scope, elem)
{
elem.addClass('an-chart-participacion');
scope.$watchGroup(['dataCurrent','dataPrev'], function()
{
if( !scope.dataCurrent || !scope.dataPrev )
return;
_drawChart(elem, scope.dataCurrent, scope.dataPrev);
});
},
};
});
angular.js - directivas
var _drawChart = function(elem, dataCurrent, dataPrev, options)
{
elem = d3.select(elem[0]);
options = _.defaults(options, { width: 50, height: 60 });
var margin = {top: 0, right: 0, bottom: 20, left: 0};
var width = options.width - margin.left - margin.right,
height = options.height - margin.top - margin.bottom;
elem.select("svg").remove();
var svg = elem.append("svg")
.attr("width", options.width)
.attr("height", options.height)
.attr("viewBox", [0, 0, options.width, options.height].join(' '))
.append('g')
.attr('transform', 'translate(0, ' + margin.top + height + ') scale(1,-1)');
…
}
Un taller de d3.js difícil y divertido*
¿qué necesitas para hacer visualizaciones
de datos impresionantes?
*http://www.macwright.org/presentations/dcjq/
Javier Abadía
@javierabadia
FIN
conceptos y ejemplos
• teoría
• selecciones
• data joins
• svg
• escalas
• animación
• layouts
• datos anidados
• adornos, tooltips, eventos
• otras libs: dc.js / crossfilter
• dimple
• bullets (html)
– selecciones, data joins
• barras horizontales (otro más
interesante?)
– svg, escalas, animación
• evolución temporal
– data joins (enter, exit), animación
• sectores
– pie, arc
• escaños
• [datos anidados]
• cajamar
Nested data – Nested selections
• selectAll().data()
– selectAll().data(function(l1) { return l1.l2_items; })
• great example: http://code.hazzens.com/d3tut/lesson_3.html

Más contenido relacionado

PDF
Dart como alternativa a TypeScript (Codemotion 2016)
PPTX
Reactividad en Angular, React y VueJS
ODP
node-db: La excusa perfecta para hablar de C++ y Node.js
PPT
MODELO PASO DE MENSAJES
PDF
Clase 6 objetos de javaScript
PDF
Clase 7 objetos globales de javaScript
PDF
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PDF
Clase 5 funciones en javaScript
Dart como alternativa a TypeScript (Codemotion 2016)
Reactividad en Angular, React y VueJS
node-db: La excusa perfecta para hablar de C++ y Node.js
MODELO PASO DE MENSAJES
Clase 6 objetos de javaScript
Clase 7 objetos globales de javaScript
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
Clase 5 funciones en javaScript

La actualidad más candente (20)

PDF
Aprende a programar con KDE y una patata
ODP
Ajax
DOCX
Practica de programacion 21 28
PDF
Ejercicios en Netbeans
PDF
08 strings o cadenas
PDF
Ejercicios resueltos practica 2 (nueva 2014) informática ii
DOCX
DOCX
Jorge informe tecnico
TXT
Lab
PDF
Ejemplo de aplicación cliente-servidor en C#
DOCX
Hechos en clase
PDF
Charla congreso web introducción programación funcional en JavaScript
PDF
Tap u2-componentes y librerias-programa para cifrar y descifrar cadenas
PDF
Curso iOS
PDF
Problemas+resueltos+de+c$2 b$2b
PDF
Sincronizar Threads
PPT
Unit Testing - Trovit
PDF
Empezando con Angular 2
PDF
José Ramón Palanco - NoSQL Security [RootedCON 2011]
DOCX
Aprende a programar con KDE y una patata
Ajax
Practica de programacion 21 28
Ejercicios en Netbeans
08 strings o cadenas
Ejercicios resueltos practica 2 (nueva 2014) informática ii
Jorge informe tecnico
Lab
Ejemplo de aplicación cliente-servidor en C#
Hechos en clase
Charla congreso web introducción programación funcional en JavaScript
Tap u2-componentes y librerias-programa para cifrar y descifrar cadenas
Curso iOS
Problemas+resueltos+de+c$2 b$2b
Sincronizar Threads
Unit Testing - Trovit
Empezando con Angular 2
José Ramón Palanco - NoSQL Security [RootedCON 2011]
Publicidad

Similar a Codemotion 2016 - d3.js un taller divertido y difícil (16)

PPT
Visualizacion de Redes en Curso gratis de Grafos
PPT
Camon visualizar-Redes
PDF
PPT
Catedra orange curso_redes
PPTX
Conceptos-HTML-y-JavaScript-Bloque-3-JavaScript.pptx
PDF
Tema 4 Visualización Avanzada Datos analíticca.pdf
PPT
Camon visualizar-2010-10-13
PPTX
Big data: a data sicentist view
PPTX
S3 2016 taller-javascript-v2
PDF
Programacion Reactiva y d3js
PDF
03. Introduccion a JavaScript y JQuery
PPTX
Sesión #1 Introduccion al curso.pptx
KEY
Javascript funcional
PDF
Curso de Verano "Datos y Gobierno Abierto" Juan Elosua
PPTX
Visualización en javascript
PPT
Javascript objetos
Visualizacion de Redes en Curso gratis de Grafos
Camon visualizar-Redes
Catedra orange curso_redes
Conceptos-HTML-y-JavaScript-Bloque-3-JavaScript.pptx
Tema 4 Visualización Avanzada Datos analíticca.pdf
Camon visualizar-2010-10-13
Big data: a data sicentist view
S3 2016 taller-javascript-v2
Programacion Reactiva y d3js
03. Introduccion a JavaScript y JQuery
Sesión #1 Introduccion al curso.pptx
Javascript funcional
Curso de Verano "Datos y Gobierno Abierto" Juan Elosua
Visualización en javascript
Javascript objetos
Publicidad

Más de Javier Abadía (12)

PPTX
Good Names - Difference between code anyone can understand and cryptic gibberish
PDF
Python Asíncrono - Async Python
PPTX
Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
PPTX
UX/UI para Desarrolladores
PPTX
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
PPTX
Retos de Programación en Python
PPTX
Django + Vue, JavaScript de 3ª generación para modernizar Django
PPTX
Vue.js + Django - configuración para desarrollo con webpack y HMR
PPTX
Anatomía de un Bot para Resultados Electorales
PPTX
Deep learning image classification aplicado al mundo de la moda
PPTX
Análisis de colores: cómo analizar tendencias de moda automáticamente
PDF
La Noche Electoral
Good Names - Difference between code anyone can understand and cryptic gibberish
Python Asíncrono - Async Python
Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
UX/UI para Desarrolladores
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
Retos de Programación en Python
Django + Vue, JavaScript de 3ª generación para modernizar Django
Vue.js + Django - configuración para desarrollo con webpack y HMR
Anatomía de un Bot para Resultados Electorales
Deep learning image classification aplicado al mundo de la moda
Análisis de colores: cómo analizar tendencias de moda automáticamente
La Noche Electoral

Último (20)

PDF
aguntenlos femboysssssssssssssssssssssssssssssss
PPTX
CREADA PARA VIVIR EN COMUNION 27 de marzo.pptx
PPTX
jajajajajajajajajajjajajajajjajajajahdegdhwgfedhgfdhdfe
PPTX
Taller_Herramientas_Digitales_para_la_Gestión_Laboral_Eficiente_SUPERSERVICI...
PPTX
Blue Pink Minimalist Modern Digital Evolution Computer Presentation.pptx
PDF
ARCHIVOS empleados en el explorador de archivos
PDF
ACCESORIOS Y ATAJOS WINDOWS empleados en Windows
DOCX
Proyecto del instituto Gilda Ballivian Rosado
PPTX
POR QUÉ LOS CRISTIANOS NO CELEBRAMOS ESTAS.pptx
PDF
AWS CloudOpS training español (Operaciones en la nube)
DOCX
TRABAJO DE ESTRATEGIA MAXIMILIANO ELIZARRARAS.docx
PPTX
4.1.1%20MEDIDAS%20DE%20CONTROL_r1PVC.pptx
PPTX
Charla 3 - La gestión de servicios de TI.pptx
PPTX
PARTE DE UNA PC _ SEIRY.pptx.........................
PDF
Tic en nuestra vida diaria en la educación
PDF
StreamSync Panel - Paneles Profesionales para la Gestión de Streaming.pdf
PDF
Trabajo Estrategia de Mejoramiento-samuel solarte.pdf
PPTX
Informática e inteligencia artificial (2).pptx
PDF
EL BRANDBOOK MUNDUS DE PERFUMERIA NICHO
PDF
MU_Gestion_Internacional_Edificacion_Construccion_MBA.pdf
aguntenlos femboysssssssssssssssssssssssssssssss
CREADA PARA VIVIR EN COMUNION 27 de marzo.pptx
jajajajajajajajajajjajajajajjajajajahdegdhwgfedhgfdhdfe
Taller_Herramientas_Digitales_para_la_Gestión_Laboral_Eficiente_SUPERSERVICI...
Blue Pink Minimalist Modern Digital Evolution Computer Presentation.pptx
ARCHIVOS empleados en el explorador de archivos
ACCESORIOS Y ATAJOS WINDOWS empleados en Windows
Proyecto del instituto Gilda Ballivian Rosado
POR QUÉ LOS CRISTIANOS NO CELEBRAMOS ESTAS.pptx
AWS CloudOpS training español (Operaciones en la nube)
TRABAJO DE ESTRATEGIA MAXIMILIANO ELIZARRARAS.docx
4.1.1%20MEDIDAS%20DE%20CONTROL_r1PVC.pptx
Charla 3 - La gestión de servicios de TI.pptx
PARTE DE UNA PC _ SEIRY.pptx.........................
Tic en nuestra vida diaria en la educación
StreamSync Panel - Paneles Profesionales para la Gestión de Streaming.pdf
Trabajo Estrategia de Mejoramiento-samuel solarte.pdf
Informática e inteligencia artificial (2).pptx
EL BRANDBOOK MUNDUS DE PERFUMERIA NICHO
MU_Gestion_Internacional_Edificacion_Construccion_MBA.pdf

Codemotion 2016 - d3.js un taller divertido y difícil

  • 1. Un taller de d3.js difícil y divertido* ¿qué necesitas para hacer visualizaciones de datos impresionantes? *http://www.macwright.org/presentations/dcjq/ Javier Abadía @javierabadia
  • 2. ¿por qué es difícil?
  • 3. ¿y por qué es divertido?
  • 5. un gráfico de barras
  • 8. logística • ¿os funciona todo? • https://github.com/jabadia/d3-workshop
  • 9. ¿qué queremos conseguir? 1. preparar los datos 2. elegir el tipo de visualización apropiado 3. buscar un ejemplo (p.ej. en bl.ocks.org) parecido 4. cambiar los datos 5. cambiar la apariencia 6. adaptar la interacción 7. integrarlo en mi app contar una historia con los datos
  • 11. Un poco de teoría d3.js, Javascript Nivel Demonio+
  • 12. d3.js • no es una herramienta de visualización – Tableau, Excel, R-studio • no es una librería de gráficas – highcharts.js, google charts, dimple, nvd3 • no es una librería de mapas – leaflet.js • no es una librería de dibujo – SVG, Canvas
  • 15. ¿qué tiene de especial? DATOS JSONCSV TSV …
  • 16. d3 necesita JS nivel Demonio+
  • 19. function aceptaDos(a, b) { a = a || ‘default A’; 🌶 b = b || ‘default B’; return a + b + arguments[2]; } aceptaDos(); // legal aceptaDos(‘pA’); // legal aceptaDos(‘pA’,’pB’); // legal aceptaDos(‘pA’,’pB’,’pC’); // legal
  • 20. function modifica1(s) { return 'un ' + s + ' precioso'; } function modifica2(s) { return 'el mejor ' + s + ' de todos'; } function generaDia(m) { return m('dia'); } generaDia(modifica1); // ‘un dia precioso’ generaDia(modifica2); // ‘el mejor dia de todos’
  • 21. function modifyString() { var prefix='|'; var postfix='|'; var output = function(s) { return prefix + s + postfix; } output.prefix = function(p) { prefix = p; return output; } output.postfix = function(p) { postfix = p; return output; } return output; } m = modifyString().prefix(‘un’).postfix(‘precioso’); m(‘dia’) // ‘un dia precioso’ ❶ ❷ ❸ ❹ ❶ ❷ ❹
  • 22. e.attr('x', function(d) { return x(d); }) e.attr('x', x) e.attr('x', function(d) { return this.x(d); })=>=>
  • 25. selecciones lis = $(‘li’) lis.length lis.each( function() { console.log(this); } ) lis.each( function() {$(this).fadeOut(); } ) 🌶 lis.each( function() {$(this).fadeIn(); } ) 🌶 lis.fadeOut() lis.fadeIn() lis.css({color: ‘red’}) <ul> <li>a</li> <li>b</li> <li>c</li> <li>d</li> <li>e</li> </ul>
  • 26. más selecciones • jQuery – $(‘li’).css(‘background-color’,’red’); • D3 – d3.selectAll(‘.bar’).attr(‘fill’,’red’); • pero… – d3.selectAll(‘.bar’).data(meses);
  • 28. <ul> <li>Java</li> <li>C</li> <li>C++</li> <li>C#</li> <li>Python</li> <li>JavaScript</li> <li>Visual Basic .NET</li> <li>Perl</li> <li>Objective-C</li> <li>Assembly language</li> <li>Swift</li> <li>Ruby</li> <li>Visual Basic</li> <li>Delphi/Object Pascal</li> <li>Go</li> <li>Groovy</li> <li>R</li> <li>MATLAB</li> <li>PL/SQL</li> </ul> var progLang = [ 'Java', 'C', 'C++', 'C#', 'Python', 'JavaScript', 'PHP', 'Visual Basic .NET', 'Perl', 'Objective-C', 'Assembly language', 'Swift', 'Ruby', 'Visual Basic', 'Delphi/Object Pascal', 'Go', 'Groovy', 'R', 'MATLAB', 'PL/SQL', ];
  • 29. var progLang = [ 'Java', …, 'PL/SQL']; var list = d3.select('ul'); var items = list.selectAll('li.lang').data(progLang); items.enter().append('li') .attr('class', 'lang') .text(String); … .text(function(d) { return String(d); }); ❶ ❸❷ ❹ ❺ ❻
  • 30. selection .attr(‘x’, function(d, i) { … }) .text(function(d, i) { … }) .property(‘selected’, function(d, i) { … }) .style(‘opacity’, function(d, i) { … }) this.__data__ function(d,i,data) { … } d = dato i = índice del dato data = array de todos los datos this = nodo DOM
  • 32. Más teoría Visualización de datos, codificación visual
  • 34. var x = d3.scaleLinear() .domain([10, 130]) .range([0, 960]); x(20); // 80 x(50); // 320 var color = d3.scaleLinear() .domain([10, 100]) .range(["brown", "steelblue"]); color(20); // "#9a3439" color(50); // "#7b5167" var x = d3.scaleTime() .domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]) .range([0, 960]); x(new Date(2000, 0, 1, 5)); // 200 x(new Date(2000, 0, 1, 16)); // 640 x.invert(200); // Sat Jan 01 2000 05:00:00 GMT-0800 (PST) x.invert(640); // Sat Jan 01 2000 16:00:00 GMT-0800 (PST)
  • 35. var x = d3.scalePoint() .domain(["a", "b", "c"]) .range([0, width]); var x = d3.scaleBand() .domain(["a", "b", "c"]) .range([0, width]) .padding(0.05); var c = d3.scaleOrdinal() .domain(["apple", "orange", "banana", "grapefruit"]) .range(["green”, ”orange”, ”yellow”, ”red"]);
  • 36. ahora si que no os libráis de las barras
  • 37. Datos dinámicos y movimiento Animación, actualización de datos, story-telling
  • 38. [ 'Python', 'JavaScript', 'PHP', 'Visual Basic .NET', 'Perl', 'Objective-C', 'Assembly language', 'Swift', 'Ruby', 'Visual Basic', 'Delphi/Object Pascal', 'Go', 'Groovy', 'R', 'MATLAB', 'PL/SQL', ] <ul> <li>Java</li> <li>C</li> <li>C++</li> <li>C#</li> <li>Python</li> <li>JavaScript</li> <li>Visual Basic .NET</li> <li>Perl</li> <li>Objective-C</li> <li>Assembly language</li> <li>Swift</li> <li>Ruby</li> <li>Visual Basic</li> <li>Delphi/Object Pascal</li> <li>Go</li> </ul> EXIT UPDATE UPDATE ENTER
  • 40. var bars = svg.selectAll('rect.bar').data(visibleWeather, day); console.log(bars.enter().size(), bars.size(), bars.exit().size()); bars.enter() // ENTER .append('rect') .attr('class','bar') .attr('x', function(d,i) { return x(i) + x.bandwidth(); }) .attr('width', x.bandwidth()) .attr('y', function(d) { return y(tempMin(d)); }) .attr('height', function(d) { return y(tempMax(d)-tempMin(d)); }) .style('fill', function(d) { return color(tempMin(d));}) .transition() .attr('x', function(d,i) { return x(i); }) bars // UPDATE .transition() .attr('x', function(d,i) { return x(i); }) .attr('width', x.bandwidth()) .attr('y', function(d) { return y(tempMin(d)); }) .attr('height', function(d) { return y(tempMax(d)-tempMin(d)); }) bars.exit() // EXIT .remove()
  • 42. going out of the box layouts, arcs, paths
  • 43. layouts • Bundle • Chord • Cluster • Force • Histogram • Pack • Partition • Pie • Stack • Tree • Treemap • … datos datos más fáciles de pintar { region: ‘Norte’, ventas: 11245 } { startAngle: 0, endAngle: 0.124, data: { region: ‘Norte’, ventas: 11245 } } data pie(data)
  • 44. arc • d3.arc() es una función que devuelve un generador de arcos – un arco es un path de SVG • se puede/suele configurar con parámetros fijos var arc = d3.arc(); arc({ innerRadius: 0, outerRadius: 100, startAngle: 0, endAngle: Math.PI / 2 }); // "M0,-100A100,100,0,0,1,100,0L0,0Z" var arc = d3.arc() .innerRadius(0) .outerRadius(100) .startAngle(0) .endAngle(Math.PI / 2); arc(); // "M0,-100A100,100,0,0,1,100,0L0,0Z"
  • 45. pie y arc trabajan juntos var arc = d3.svg.arc() .outerRadius(radius - 10) .innerRadius(0); var pie = d3.layout.pie() .sort(null) .value(function(d) { return d.population; }); var g = svg.selectAll(".arc").data(pie(countries)) .enter().append("path") .attr("class", "arc") .attr("d", arc) .style("fill", function(d) { return color(d.data.age); }); la mitad de los parámetros la otra mitad WTF? http://bl.ocks.org/mbostock/3887235
  • 47. tu propio layout var resultados = [ {sCandidatura: ’pp', iEscanos: 23 }, {sCandidatura: ’psoe', iEscanos: 20 }, {sCandidatura: ’podemos', iEscanos: 11 }, {sCandidatura: ’ciudadanos', iEscanos: 7 }, ];
  • 48. nos preparamos los datos var resultados = [ {sCandidatura: ’pp', iEscanos: 23 }, {sCandidatura: ’psoe', iEscanos: 20 }, {sCandidatura: ’podemos', iEscanos: 11 }, {sCandidatura: ’ciudadanos', iEscanos: 7 }, ]; var diputados = [ ’pp0’, ‘pp1’, ’pp2’, …, ’pp22’, ‘psoe0’, ’psoe1’, …,’psoe19’, ’podemos0’, …, …, ’ciudadanos6’ ];
  • 49. mi layout var squaresLayout = function(squaresPerRow, width, gapRatio) { var squareSize = width / (squaresPerRow + (squaresPerRow-1) * gapRatio); var gapSize = squareSize * gapRatio; var layout = function(data) { return _.map(data, function(d, i) { var row = Math.floor(i / squaresPerRow); var col = i - (row*squaresPerRow); return { row: row, col: col, x: col * squareSize + col * gapSize, y: row * squareSize + row * gapSize, data: d, }; }); } layout.squareSize = squareSize; layout.gapSize = gapSize; layout.squaresPerRow = squaresPerRow; return layout; }; layout = squaresLayout(escanosPorFila, width, gapRatio); var squares = svg.select('.squares').datum(diputados) .selectAll('rect.square').data(layout, function(d) { return d.data.idDiputado; }); WTF?
  • 63. d3.js v3 ▶v4 no toques… ¿por que tocas?
  • 64. librería modular v3 <script src="https://d3js.org/d3.v3.js"></script> v4 <script src="https://d3js.org/d3.v4.js"></script> <script src="https://d3js.org/d3-array.v1.min.js"></script> <script src="https://d3js.org/d3-collection.v1.min.js"></script> <script src="https://d3js.org/d3-color.v1.min.js"></script> <script src="https://d3js.org/d3-format.v1.min.js"></script> <script src="https://d3js.org/d3-interpolate.v1.min.js"></script> <script src="https://d3js.org/d3-time.v1.min.js"></script> <script src="https://d3js.org/d3-time-format.v2.min.js"></script> <script src="https://d3js.org/d3-scale.v1.min.js"></script>
  • 66. cambian los joins v3 v4 var circle = svg.selectAll("circle").data(data) // UPDATE .style("fill", "blue"); // ENTER; modifies UPDATE! 🌶 circle.enter().append("circle") .style("fill", "green"); circle // ENTER + UPDATE .style("stroke", "black"); circle.exit().remove(); // EXIT var circle = svg.selectAll("circle").data(data) // UPDATE .style("fill", "blue"); circle.enter().append("circle") // ENTER .style("fill", "green") .merge(circle) // ENTER + UPDATE .style("stroke", "black"); circle.exit().remove(); // EXIT
  • 67. otros cambios • mejor soporte para Canvas (d3-shape) • transiciones coordinadas • muchos otros cambios menores – https://iros.github.io/d3-v4-whats-new
  • 69. la convención de márgenes var margin = {top: 20, right: 10, bottom: 20, left: 10}; var width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); http://bl.ocks.org/mbostock/3019563 var x = d3.scale.linear() .range([0, width]); // area útil var y = d3.scale.linear() .range([height, 0]); // area útil
  • 70. angular.js - directivas <div class="participacion" an-chart-participacion data-current='dataCurrent' data-prev='dataPrev'> </div>
  • 71. angular.js - directivas module.directive('anChartParticipacion', function() { var _drawChart = function(elem, dataCurrent, dataPrev, options) { … // codigo d3 aquí … }; return { restrict: 'A', scope: { dataCurrent: '=current', dataPrev: '=prev', }, link: function(scope, elem) { elem.addClass('an-chart-participacion'); scope.$watchGroup(['dataCurrent','dataPrev'], function() { if( !scope.dataCurrent || !scope.dataPrev ) return; _drawChart(elem, scope.dataCurrent, scope.dataPrev); }); }, }; });
  • 72. angular.js - directivas var _drawChart = function(elem, dataCurrent, dataPrev, options) { elem = d3.select(elem[0]); options = _.defaults(options, { width: 50, height: 60 }); var margin = {top: 0, right: 0, bottom: 20, left: 0}; var width = options.width - margin.left - margin.right, height = options.height - margin.top - margin.bottom; elem.select("svg").remove(); var svg = elem.append("svg") .attr("width", options.width) .attr("height", options.height) .attr("viewBox", [0, 0, options.width, options.height].join(' ')) .append('g') .attr('transform', 'translate(0, ' + margin.top + height + ') scale(1,-1)'); … }
  • 73. Un taller de d3.js difícil y divertido* ¿qué necesitas para hacer visualizaciones de datos impresionantes? *http://www.macwright.org/presentations/dcjq/ Javier Abadía @javierabadia FIN
  • 74. conceptos y ejemplos • teoría • selecciones • data joins • svg • escalas • animación • layouts • datos anidados • adornos, tooltips, eventos • otras libs: dc.js / crossfilter • dimple • bullets (html) – selecciones, data joins • barras horizontales (otro más interesante?) – svg, escalas, animación • evolución temporal – data joins (enter, exit), animación • sectores – pie, arc • escaños • [datos anidados] • cajamar
  • 75. Nested data – Nested selections • selectAll().data() – selectAll().data(function(l1) { return l1.l2_items; }) • great example: http://code.hazzens.com/d3tut/lesson_3.html

Notas del editor

  • #3: porque hay que saber Javascript nivel Demonio+ (*) porque hay que saber cómo funciona la visualización de datos porque hay que saber contar historias * pinchito aka Alex Fernandez en madrid-js, 24/Ago/2016
  • #4: por las mismas razones!
  • #8: http://www.global-migration.info/
  • #10: contar una historia la principal dificultad es ENTENDER LOS DATOS
  • #11: http://www.global-migration.info/
  • #16: flexible versatil aprovecha los estándares web (HTML, CSS, SVG) javascript JSON
  • #19: porque identificar objetos es una de las partes principales de los joins
  • #20: programación funcional, lodash, http://www.smashingmagazine.com/2014/07/dont-be-scared-of-functional-programming/
  • #21: cuidado si el 0 es un valor aceptable
  • #22: las funciones se pueden pasar como parámetro
  • #23: las funciones puede devolver funciones son objetos, las funciones pueden tener métodos 3. closures 4. funciones encadenables
  • #24: equivalencias a recordar
  • #31: seleccionar la lista seleccionar todos los items de la lista vincular con el array de datos para cada dato que no tiene un elemento correspondiente añadir un li al cual le ponemos la clase lang y le ponemos el texto ¿? function(d) { return String(d); }
  • #32: funciones encadenables aceptan una función se le pasa como parámetro el dato y el índice y el conjunto de nodos: this es el elemento del DOM this.__data__ contiene el dato
  • #36: https://medium.com/@mbostock/introducing-d3-scale-61980c51545f#.mtiu0latw
  • #75: el taller de PHP es en la otra sala