pondělí 23. listopadu 2015

#dataviz15 #6 D3.js

V hodině o základech D3.js hodně mých spolužáků tápalo. Rozhodl jsem se trochu osvětlit, jaké kroky vedly k výsledku. Zde je fiddle:

Nejprve voláme funkci d3.csv(url, callback). Ta stáhne soubor na url a zavolá funkci callback jakmile je soubor stažen.

Jako callback předáme naši vlastní funkci – tato funkce obdrží od D3 data, se kterými můžeme pracovat. Dovnitř funkce napíšeme celý náš program.

Naše funkce má jako parametr data. Přesně tam budou data z csv souboru a můžeme s nimi dále pracovat. Jsou uloženy jako pole řádků z našeho souboru. Pole je datová konstrukce ze světa programování. Umožňuje mít více hodnot v jednom objektu, jedné proměnné. Hodnoty jsou očíslované – něco jako šuplíčky s čísly.

Zdrojový CSV soubor má 2 řádky, ale protože první řádek chápe D3 jako názvy sloupců, je v našem poli právě jeden řádek. Ten získáme jako data[0]. Počítáme od nuly. Hodnota v prvním chlívečku je objekt. Objekt je si lze představit jako šuplíčky, které mají jméno. V našem případě jsou mají šuplíčky popisky roky 2000-2014. V šuplíčcích se skrývají číselné hodnoty pro jednotlivé roky. Uff.

Možná někoho napadá, že naše csv vlastně mohlo mít jako popisky sloupců “rok” a “hodnota”- V jednotlivých řádcích by pak mělo rok a hodnota. Celé by to pak bylo jednodušší. Naštěstí, protože d3 je mocný nástroj, umožní nám takovou věc udělat velice snadno. (To se na hodině neukazovalo – tj. to vylepšení v rámci DÚ).

var rows = d3.entries(data[0]);



Do proměnné rows uložíme výsledek volání d3.entries(data[0]). To je funkce d3, která udělá z objektu pole. Jak? Vezme z šuplíčku nálepku (klíč - key) a jeho obsah (value) a vloží je do nového šuplíčku v poli. Nyní tedy máme v proměnné rows uloženy jednotlivé řádky tak, jak bychom si je přáli. Každý řádek má svůj klíč a svou hodnotu.

var chart = d3.select("#chart");

Také si založíme proměnou chart. Její obsahem bude HTML element s id ‘chart’. Teď přijde složitější konstrukce:

var row = chart.selectAll('div')
.data(rows)
.enter()
.append('div');

Ta říká: Z elementu chart vyber všechny elementy div (i budoucí). Ty svážeme s daty – s řádky z proměnné rows. Pak říkáme, co se má stát, když přijdou nová data (enter) – nový řádek. V tom případě se má k vybraným ‘divům’ přidat další ‘div’.

row.append('div')
.text(function (d) {
return d.key;
})
.classed('label', true);

Do každého řádku přidáme další div. To bude popisek s rokem. Nastavíme mu text. Abychom se dostali k datům, tak jako parametr předáme funkci. Ta funkce od d3 obdrží právě jeden řádek, který pochází z těch dat, které jsme svázali s každým divem. Ten řádek bude v parametru d. To je objekt – má dva šuplíčky, jeden se jmenuje key a druhý value. Jsou to přesně ty samé jako jsem o nich hovořil výše. V šuplíčku key je uložen rok a ten nás přesně zajímá. Proto vrátíme (return) hodnotu z šuplíčku d.key. Ta se použije jako text divu. Také nastavíme novému divu třídu ‘label’.

row.append('div')
.classed('bar', true)
.text(function (d) {
return d.value;
})
.style('width', function (d) {
return d.value / 2000 + 'px';
});

Ke každému řádku přidáme ještě jeden div. To bude sloupec našeho grafu. Nastavíme mu třídu ‘bar’ a jako text mu vložíme hodnotu ze šuplíčku ‘value’. Předáme mu ještě styl. Tím je jeho šířka. Tedy šířka sloupce grafu. Zde by se hodila použít nějaká škála, pro zjednodušení prostě vydělíme naše data. Šířku vypočteme tak, že vydělíme hodnotu 2000, aby nebyl sloupec příliš široký.


To je z javascriptového kódu vše. Zbývá jen nastylovat náš graf, aby hodnoty pěkně vynikly.

.bar {
background: #99f;
height: 20px;
margin-bottom: 5px;
margin-left: 50px;
color: white;
}
.label {
float: left;
width: 50px;
}

body {
font-family: sans-serif;
font-size: 12px;
}

Výsledek:


image


PS: Upřímně pochybuji, že někdo z mého popisu pochopil vo co tady de. Ale alespoň jsem to zkusil. A selhal.