Vytvoření liniového grafu v D3.js v. 5

nastal čas zintenzivnit naši hru a vytvořit liniový graf od nuly. A ne jen tak ledajaký řádkový graf: vícesériový graf, který pojme libovolný počet řádků. Kromě manipulace s více řádky budeme pracovat s časovými a lineárními měřítky, osami a štítky – nebo spíše nechat je pracovat pro nás. Je tu spousta práce, takže navrhuji, abyste vypálili svůj server D3 a pustili se do praskání.

vytvoříme tuto krásu! Zábava!

Příprava Dokumentu

Jako první krok musíme připravit data a strukturu souboru pro vizualizaci. Vytvořit line_chart.html, styly.css a data.csv ve složce projektu a naplnit je s úryvky, které následují. To nám pomůže začít.

Vložte toto do řádku.html soubor. Kód definuje prvek svg pro nás, takže můžeme začít kreslit hned. Také jsem předem vytvořil základní strukturu, takže je snazší procházet dokument, když pracujeme na jeho konkrétních částech.

nechte styly.css dokument zatím prázdný. Vložte následující řádky do dat.csv. Linka graf bude obsahovat více série: odpovídající sloupce a, B a C.

date,A,B,C20-Jul-2019,10,20,1621-Jul-2019,11,22,1822-Jul-2019,13,19,2123-Jul-2019,11,17,2224-Jul-2019,15,16,2025-Jul-2019,16,19,1826-Jul-2019,19,21,1827-Jul-2019,22,25,1528-Jul-2019,18,24,1229-Jul-2019,14,20,1630-Jul-2019,14,18,1831-Jul-2019,16,18,2101-Aug-2019,15,20,2202-Aug-2019,14,21,19

Příprava Dat

první krok – a to zásadní krok pro celou vizualizaci – je správně přečíst data. Použil jsem příklad více sérií z nějakého důvodu: i když je to docela jednoduché vykreslit jednu cestu, zpracování více řádků (zejména nedefinovaný počet z nich) vyžaduje trochu více jemnosti D3. Vložte následující do datové sekce, znovu načtěte dokument html a zkontrolujte protokol konzoly v prohlížeči:

const timeConv = d3.timeParse("%d-%b-%Y");const dataset = d3.csv("data.csv");dataset.then(function(data) { const slices = data.columns.slice(1).map(function(id) { return { id: id, values: data.map(function(d){ return { date: timeConv(d.date), measurement: +d }; }) }; });console.log("Column headers", data.columns);console.log("Column headers without date", data.columns.slice(1));// returns the sliced datasetconsole.log("Slices",slices); // returns the first sliceconsole.log("First slice",slices);// returns the array in the first sliceconsole.log("A array",slices.values); // returns the date of the first row in the first sliceconsole.log("Date element",slices.values.date); // returns the array's lengthconsole.log("Array length",(slices.values).length);

podívejme se na transformace nazvané na naší datové sadě jeden po druhém– – data.sloupce vrátí záhlaví csv-data.sloupec.slice(1) vrátí csv záhlaví bez data sloupec (plátek začíná na sloupec indexován v 1) – mapa() volání funkce na každý prvek pole (sestávající z a, B a C) – řekněme, každý z těchto prvků ‚krajíc’– mapa() přiřadí sloupci název jako id prvek pro každý řez– pak přiřadí hodnoty pole na každý plátek– všimněte si, jak hodnoty prvku vyvolává funkce. Zde mapujeme informace z původní datové sady: pole se bude skládat ze 2 sloupců, data a měření. Data je odvozen z prvního sloupce (a transformovány do formátu data), a měření je převzat z kolony odpovídající plátek id.Na konci těchto transformací dostaneme 3 pole: A, B, a C, s 2 sloupce: datum a měření. Jedná se o úžasně flexibilní způsob, jak rozdělit datovou sadu: bez ohledu na to, kolik sloupců má! Všechno se to dělá v těch několika řadách. Vytiskl jsem nějaké informace do konzoly, abych vám pomohl zkontrolovat úryvek.

Console log

Recenze protokolu konzoly pro více informací

Váhy Příprava

Poté, co data byla přečtena v musíme nastavit škálování mechanismus. To se provádí za účelem tisku grafu v souladu s nemovitostmi svg. Váhy transformují vstup dat (naše data a hodnoty) na souřadnice v rovině svg. Vložte následující řádky do sekce váhy.

const xScale = d3.scaleTime().range();const yScale = d3.scaleLinear().rangeRound();xScale.domain(d3.extent(data, function(d){ return timeConv(d.date)}));yScale.domain();

vykreslíme data na ose x a hodnoty na ose y. D3 poskytuje metodu scaleTime() pro škálování dat a metodu scaleLinear() pro spojité hodnoty. Nejprve se rozhodneme o rozsahu stupnice: na co by měly být vstupní hodnoty přeloženy. V tomto případě roztáhneme datové hodnoty z 0 na šířku svg a číselné hodnoty z výšky svg na 0. Jako druhý krok určíme doménu vstupních dat. Doména se skládá ze všech hodnot mezi zadaným minimem a maximem, které může datová sada trvat. Místo toho, abychom tyto hodnoty ručně vyhledali, projdeme je vestavěnými funkcemi D3: – d3.rozsah () vrací minimální a maximální hodnotu pole (v přirozeném pořadí) – to bude fungovat perfektně na našem datovém setu-d3.max () vrací maximální hodnotu pole. Všimněte si, jak v tomto příkladu nejprve extrahujeme maximální hodnotu z každého pole a poté vybereme maximum všech tří. Také jsem přidal 4 k maximální hodnotě z čistě subjektivních estetických důvodů: chtěl jsem mít nad grafem nějaký prostor.

váhy jsou nyní nastaveny. Pokud nemáte dostatek měřítek a chtěli byste vidět více příkladů, podívejte se na můj předchozí tutoriál.

dobře nakonfigurované váhy nám umožňují začít vykreslovat hodnoty na svg. Pokaždé, když evokujeme datovou sadu, stačí na ni zavolat vhodnou stupnici.

osy

dost chatování-pojďme už něco nakreslit! Osy jsou dobrým výchozím bodem: pokud jsou vykresleny správně, ujistí nás, že data byla přečtena podle očekávání a že se škálují tak pěkně, jak jsme si představovali.

Vložte toto do OS v části Příprava:

const yaxis = d3.axisLeft().scale(yScale); const xaxis = d3.axisBottom().scale(xScale);

a to na osy pod kreslicí částí:

svg.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(xaxis);svg.append("g") .attr("class", "axis") .call(yaxis);

a tak jednoduché, jak jsme vykreslili osy x a y!

osy jsou zde!

je pravda, že osy nejsou nejelegantnější na světě (tam jsou některé pěkné osy venku), ale jsou tady! Existuje několik dalších vylepšení, které můžeme použít, aby byly pro čtenáře přátelštější.

podívejme se nejprve na osu x: s daty se děje něco vtipného. Čtení zleva, dostaneme ‚So 20‘, ‚Jul 21‘, ‚Mon 22‘, a v určitém okamžiku se dostaneme jen ‚Srpen‘. Zdá se, že měsíce a dny přišly v nepodřízené směsi variací. Musíme dát a ukončit tento freestyle, a tím myslím, že bychom se měli rozhodnout, jaký formát data bychom chtěli vytisknout na obrazovce. D3.metoda axis() nám umožňuje nastavit všechny druhy věcí pro klíšťata – jejich počet – interval mezi body, formát zobrazení atd. Pojďme nakonfigurovat některé z nich pro obě osy.

nahraďte definici OS v sekci Příprava následujícím úryvkem a obnovte vizualizaci:

const yaxis = d3.axisLeft() .ticks((slices.values).length) .scale(yScale);const xaxis = d3.axisBottom() .ticks(d3.timeDay.every(1)) .tickFormat(d3.timeFormat('%b %d')) .scale(xScale);

výše uvedený kód určuje nastavený počet klíšťat pro osu y (14 nebo tolik, kolik je prvků pole / řádků csv). V případě osy x bude klíště zobrazeno s granularitou dne, každý den. Toho bylo dosaženo nastavením vlastnosti tick na d3.timeDay.každý (1). Formát zobrazených dat zobrazí den a zkrácený měsíc pro každé zaškrtnutí. Po těchto změnách skončíme s poněkud vylepšenými osami:

Ordnung, konečně

neposlušná data již nejsou problémem!

aby to bylo ještě lepší (je to vůbec možné!!!) můžeme přidat štítek k ose y, abychom ukázali, co hodnoty znamenají. Zatímco data jsou samovysvětlující, čísla sama o sobě neobsahují žádné informace. Přidejte štítek (říkejte mu, jak chcete – šel jsem s frekvencí) připojením následujícího obrázku k výkresu osy y:

//this you hadsvg.append("g") .attr("class", "axis") .call(yaxis)//this you append .append("text") .attr("transform", "rotate(-90)") .attr("dy", ".75em") .attr("y", 6) .style("text-anchor", "end") .text("Frequency");

(Tam je žádný styl nastavit pro štítek, takže to nebude zobrazovat v grafu – ale věřte mi a Google Chrome developer tools, je tam)

Label

Na ose y označení je neviditelná

a Konečně, pojďme zlepšit vzhled os. Tím zlepšit myslím: nastavit barvy, šířky a Vykreslování každého jednotlivého prvku, a rozhodnout, písmo použít. Vložte následující do souboru css a neváhejte se rozhodovat o svém vlastním stylu:

/* AXES *//* ticks */.axis line{stroke: #706f6f;stroke-width: 0.5;shape-rendering: crispEdges;}/* axis contour */.axis path {stroke: #706f6f;stroke-width: 0.7;shape-rendering: crispEdges;}/* axis text */.axis text {fill: #2b2929;font-family: Georgia;font-size: 120%;}

klíšťata jsou řízena .linka prvek osy, zatímco skutečná osa je nastavena pomocí .prvek cesty. Osy vypadají ostře (pokorný názor autora) a jsou připraveny přivítat některá data:

Prettified osy

bez dalších okolků, pojďme vykreslit graf!

řádkový Graf

řádky jsou v podstatě d3.cesty (), které spojují spoustu (x, y) souřadnic na 2D rovině. Chcete-li vytvořit čáru, musíte jí říct, Kde najít její souřadnice x a y, a poté je připojit k svg. Vložte následující úryvky do dříve vytvořených zástupných symbolů a společně zkontrolujeme kód.

To by se dostal do LINIE trochu v rámci Přípravy oddíl:

const line = d3.line() .x(function(d) { return xScale(d.date); }) .y(function(d) { return yScale(d.measurement); });

V tomto úryvku jsme volali linku konstruktor, d3.linka (), která používá dva přístupové prvky: x pro hodnoty ve vodorovné rovině a y pro svislou osu. Zde jednoduše poukazujeme na nejproblematičtější hodnoty našeho pole, data a měření(není čas se starat o vnořenou strukturu csv). Po dokončení vložte následující řádky do sekce kreslení:

const lines = svg.selectAll("lines") .data(slices) .enter() .append("g"); lines.append("path") .attr("d", function(d) { return line(d.values); });

to vyžaduje nějaké vysvětlení. Proměnná čáry vybere neidentifikovaný počet řádků z svg – a okamžitě řekne D3, že budou 3 řádky ukazováním na sady řezů (řádky a ,B A C). Ke každému z nich pak připojí prvek g: seskupovací prvek, který nám v pravý čas usnadní život. G prvek bude sbírat vše, co má co do činění s konkrétním grafu series (aka plátek v poli): line (zastoupeny výše jako cesta), jeho datové body, které budeme moci vznášet se nad, a sérii etiket.

první věc, kterou se připojí k řádkům (které jsou ve skutečnosti 3 prázdné g kontejnery), jsou samotné čáry grafu. Říkáme d3.line () Konstruktor na datech nakreslit cestu. Podívejte se, jak nejprve musíme přistupovat k hodnotám pod každým řezem. To je pak předán konstruktoru, který táhne data a měření podle potřeby.

Po uložení změn, zobrazení se aktualizuje se to:

Místo řádku grafu máme hory grafu

Ok, tohle není dokonalé, ale věřte mi, že jsme se tam dostat! Použijme na graf nějaké estetické opravy a pozorujme, jak se formuje. Připojte ke stylům následující.css:

/* LINE CHART */path {fill: none;stroke: #ed3700;}

musíme nastavit výplň na none, aby se tvary znovu objevily jako čáry. Aktualizovat graf:

řádky se objevily

to, Co odděluje spojnicový graf z pár řádků přilepená společně na grafu? Schopnost rozlišovat mezi sériemi. V tuto chvíli máme pouze první.

pro začátek musíme rozlišovat mezi řádky v kódu. Pojďme přidat id pro každý řádek třídy přidejte následující ŘÁDKY v sekci Příprava součástí:

let id = 0;const ids = function () { return "line-"+id++;}

Tento kousek kódu vytvoří počítadlo, které můžeme využít pro automatické přiřazení id linky pro každý přidaný řádek. Podívejme se na čítač ve třídě vlastností cest. Upravte kód v části řádky a přidejte vlastnost třídy:

const lines = svg.selectAll("lines") .data(slices) .enter() .append("g"); lines.append("path") .attr("class", ids) .attr("d", function(d) { return line(d.values); });

a magicky, každá cesta dostane svou vlastní třídu!

Path třídy

linky jsou vzhledem k jejich vlastní identitě,

to, Co zbylo pro nás udělat, je odkaz těchto tříd v css a dát každá linka svůj vlastní jedinečný charakter. Změňte část řádku grafu css říkat:

/* LINE CHART */path.line-0 {fill: none;stroke: #ed3700;}path.line-1 {fill: none;stroke: #2b2929;stroke-dasharray: 2;}path.line-2 {fill: none;stroke: #9c9c9c;stroke-dasharray: 6;}

Všimněte si, jak nejen měním barvu, ale také měním tah každého řádku. Pamatujte, že asi 10% všech lidí má určitý stupeň barvosleposti a ve vší spravedlnosti může být rozlišování mezi barvami pro každého z nás obtížné. Barvy se prostě spojí, pokud je příliš mnoho datových řad a jejich odstín se na každém monitoru zobrazí jinak.

Po změnách byly použity, řádky od sebe jasně odděleny na grafu – viz níže:

linky jsou vizuálně odlišné od sebe navzájem

série jsou diferencované, ale pořád to je nemožné říci, který je který, pokud nemáte zpaměti, podkladová data a mít dost nemocný vizuální představivost v tom případě by mě zajímalo, proč potřebuješ graf na prvním místě. Abychom většině z nás pomohli při rozpoznávání série, navrhuji připojit název série na pravou stranu grafu. Přidejte následující do sekce kreslení čar:

lines.append("text") .attr("class","serie_label") .datum(function(d) { return { id: d.id, value: d.values}; }) .attr("transform", function(d) { return "translate(" + (xScale(d.value.date) + 10) + "," + (yScale(d.value.measurement) + 5 ) + ")";}) .attr("x", 5) .text(function(d) { return ("Serie ") + d.id; });

úryvek lokalizuje konec každého řádku a připojí k němu textový prvek. Text bude vytištěn jako Serie A, Serie B nebo Serie C, v závislosti na řádku. Chcete-li Upravit štítky sérií, přidejte do dokumentu css následující:

.serie_label {fill: #2b2929;font-family: Georgia;font-size: 80%;}

štítky jsou připojeny! Čas.

každá série má svůj vlastní štítek

všichni se shodneme, že se jedná o jeden hezký řádek! Vložil jsem celý kód níže. Nezapomeňte se podívat na druhou část tutoriálu, která představuje dva scénáře přidání interaktivity do grafu.

Následujte mě na Twitteru pro více dat-sciency / vizualizace dat projekty!

ukázky kódu

line_chart.html:

styly.css:

/* AXES *//* ticks */.axis line{stroke: #706f6f;stroke-width: 0.5;shape-rendering: crispEdges;}/* axis contour */.axis path {stroke: #706f6f;stroke-width: 0.7;shape-rendering: crispEdges;}/* axis text */.axis text {fill: #2b2929;font-family: Georgia;font-size: 120%;}/* LINE CHART */path.line-0 { fill: none; stroke: #ed3700;}path.line-1 { fill: none; stroke: #2b2929; stroke-dasharray: 2;}path.line-2 { fill: none; stroke: #9c9c9c; stroke-dasharray: 6;}.serie_label { fill: #2b2929; font-family: Georgia; font-size: 80%;}

date.csv: