Vonaldiagram készítése D3-ban.js v. 5

eljött az idő, hogy fokozzuk a játékunkat, és létrehozzunk egy vonaldiagramot a semmiből. És nem akármilyen Vonaldiagram: többsoros grafikon, amely tetszőleges számú sort képes befogadni. Amellett, hogy több vonalat kezelünk, idővel és lineáris skálákkal, tengelyekkel és címkékkel fogunk dolgozni – vagy inkább, hogy nekünk dolgozzanak. Rengeteg tennivaló van, ezért azt javaslom, hogy indítsa el a D3 szervert, és kezdjük el feltörni.

létrehozzuk ezt a szépséget! Jó móka!

dokumentum előkészítés

első lépésként elő kell készítenünk az adatokat és a fájlszerkezetet a megjelenítéshez. Line_chart létrehozása.html, stílusok.css és adatok.CSV a projekt mappájában, és töltse fel őket a következő kódrészletekkel. Ez majd beindít.

illessze be ezt a line_chart-ba.html fájl. A kód meghatározza számunkra az svg elemet, így azonnal elkezdhetjük a rajzot. Létrehoztam egy alapstruktúrát is előre, így könnyebb navigálni a dokumentumban, amikor az adott szakaszokon dolgozunk.

hagyja el a stílusokat.a css dokumentum egyelőre üres. Illessze be a következő sorokat az adatokba.csv. A vonaldiagram több sorozatot tartalmaz: az A, B és C oszlopoknak felel meg.

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

Adatelőkészítés

az első lépés – és a teljes vizualizáció szempontjából döntő lépés – az adatok helyes olvasása. Többsoros példát használtam okkal: bár elég egyszerű egyetlen utat ábrázolni, több sor kezelése (különösen egy meghatározatlan szám) valamivel több D3 finomságot igényel. Illessze be a következőket Az adatok szakaszba, töltse be újra a html dokumentumot, majd tekintse át a konzol naplóját a böngészőben:

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);

nézzük át egyenként az adatkészletünkre hívott átalakításokat: – adatok.oszlopok visszaadja a csv fejlécek-adatok.oszlopok.a slice(1) a CSV fejléceket adja vissza a dátum oszlop nélkül (a szelet az 1 – nél indexelt oszlopnál kezdődik) – a map() függvényt hív a tömb minden elemén (amely A, B és C)– hívjuk mindegyik elemet szeletnek– a map() az oszlop nevét azonosító elemként rendeli minden szelethez– ezután érték tömböt rendel minden szelethez-vegye figyelembe, hogy az értékek elem hogyan idézi elő a függvényt. Itt az eredeti adathalmaz adatait térképezzük fel: a tömb 2 oszlopból, dátumból és mérésből áll. A dátum az első oszlopból származik (és dátumformátummá alakul), a mérés pedig a szeletnek megfelelő oszlopból származik id.At a transzformációk végén 3 tömböt kapunk: A, B és C, egyenként 2 oszloppal: dátum és mérés. Ez egy hihetetlenül rugalmas módja annak, hogy szelet fel egy adathalmaz: függetlenül attól, hogy hány oszlop van! Ez mind abban a néhány sorban történik. Kinyomtattam néhány információt a konzolra, hogy segítsen áttekinteni a részletet.

Konzolnapló

további információkért tekintse át a konzolnaplót

mérlegkészítés

az adatok elolvasása után be kell állítanunk a méretezési mechanizmust. Ez annak érdekében történik, hogy a diagramot az svg ingatlanának megfelelően nyomtassa ki. A skálák az adatbevitelt (dátumainkat és értékeinket) az svg síkon lévő koordinátákká alakítják át. Illessze be a következő sorokat a mérleg szakaszba.

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

a dátumokat az x tengelyen, az értékeket pedig az y tengelyen ábrázoljuk. A D3 egy scaleTime() metódust biztosít a dátumok méretezéséhez, és egy scaleLinear() metódust a folyamatos értékekhez. Először eldöntjük a skála tartományát: mire kell lefordítani a bemeneti értékeket. Ebben az esetben az adatértékeket 0-tól az svg szélességéig, a numerikus értékeket pedig az svg magasságától 0-ig nyújtjuk. Második lépésként megadjuk a bemeneti adattartományt. A tartomány az adathalmaz által meghatározott minimum és maximum közötti összes értékből áll. Ahelyett, hogy manuálisan keresné ezeket az értékeket, átadjuk a beépített D3 függvényeken: – d3.az Extension() egy tömb minimális és maximális értékét adja vissza (természetes sorrendben) – Ez tökéletesen működik a D3 dátumkészletünkön.a max () A tömb maximális értékét adja vissza. Vegye figyelembe, hogy ebben a példában először kivonunk egy maximális értéket az egyes tömbökből, majd kiválasztjuk mind a három maximumot. Tisztán szubjektív esztétikai okokból 4-et is hozzáadtam a maximális értékhez: szerettem volna egy kis helyet a grafikon felett.

a mérlegek most be vannak állítva. Ha nincs elég skálája, és további példákat szeretne látni, nézze meg az előző bemutatómat.

a jól konfigurált skálák lehetővé teszik számunkra, hogy elkezdjük ábrázolni az értékeket az svg-n. Minden alkalommal, amikor felidézzük az adatkészletet, csak meg kell hívnunk egy megfelelő skálát.

tengelyek

elég csevegés – rajzoljunk már valamit! A tengelyek jó kiindulópontok: ha helyesen ábrázolják, akkor biztosítják számunkra, hogy az adatokat a várt módon olvasták, és olyan szépen skálázódnak, mint azt elképzeltük.

illessze be ezt a tengelyekre az előkészítési szakasz alatt:

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

ez pedig a rajz szakasz alatti tengelyekhez:

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

és olyan egyszerű, mint az x és y tengelyek ábrázolása!

itt vannak a tengelyek!

igaz, hogy a tengelyek nem a legelegánsabbak a világon (vannak szép tengelyek odakint), de itt vannak! Van néhány további csípés, amelyet alkalmazhatunk, hogy barátságosabbá tegyük őket az olvasó számára.

nézzük először az x tengelyt: van valami vicces a dátumokkal. Balról olvasva ‘Sat 20’, ‘Jul 21’, ‘Mon 22’, és egy bizonyos ponton csak ‘August’ – ot érünk el. Úgy tűnik, hogy a hónapok és napok fegyelemsértő variációk keverékével jöttek. Be kell fejeznünk ezt a freestyle-t, és ez alatt azt értem, hogy el kell döntenünk, hogy milyen dátumformátumot szeretnénk nyomtatni a képernyőn. A d3.az axis() módszer lehetővé teszi számunkra, hogy mindenféle dolgot beállítsunk a kullancsokhoz – azok számát, A pontok közötti intervallumot, a megjelenítési formátumot stb. Állítsunk be néhányat mindkét tengelyre.

cserélje ki az előkészítés szakaszban szereplő tengelydefiníciót a következő részletre, majd frissítse a vizualizációt:

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);

a fenti kód meghatározza az y tengely meghatározott számú kullancsát (14, vagy annyi, ahány tömb elem / csv sor van). Abban az esetben, az x tengely egy kullancs jelenik meg egy részletességgel egy nap, minden nap. Ezt úgy sikerült elérni, hogy a tick tulajdonságot d3-ra állította.időnap.minden(1). A megjelenített dátumok formátuma megmutatja az egyes kullancsok napját és rövidített hónapját. E változások után kissé javított tengelyekkel zárulunk:

Ordnung, végre

az engedetlen dátumok már nem jelentenek problémát!

annak érdekében, hogy még jobb (ez még lehetséges!!!) hozzáadhatunk egy címkét az y tengelyhez, hogy megmutassuk, mit jelentenek az értékek. Míg a dátumok magától értetődőek, a számok önmagukban nem tartalmaznak információt. Adjon hozzá egy címkét (hívja, ahogy tetszik – gyakorisággal mentem) az alábbiak hozzáadásával az y tengely rajzához:

//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");

(a címkéhez nincs stíluskészlet, így nem jelenik meg a grafikonon – de hidd el nekem és a Google Chrome fejlesztői eszközeinek, ott van)

címke

az y tengely címke láthatatlan

végül javítsuk a tengelyek megjelenését. Javítás alatt azt értem: állítsa be minden egyes elem színét, szélességét és renderelését, és döntse el a használni kívánt betűtípust. Illessze be a következőket a css fájlba, és nyugodtan hozza meg saját stílusbeli döntéseit:

/* 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%;}

a kullancsok által ellenőrzött .vonal eleme a tengely, míg a tényleges tengely van beállítva a .path elem. A tengelyek élesek (a szerző szerény véleménye), és készen állnak néhány adat fogadására:

Prettified tengelyek

minden további nélkül ábrázoljuk a diagramot!

Vonaldiagram

a vonalak lényegében d3.útvonalak (), amelyek egy csomó (x, y) koordinátát kötnek össze egy 2D síkon. Egy vonal felépítéséhez meg kell mondani, hogy hol találja meg az x és y koordinátákat, majd ezt hozzá kell fűzni az svg-hez. Illessze be a következő kódrészleteket a korábban létrehozott helyőrzőkbe, és nézzük át együtt a kódot.

ez a sorok bitje az előkészítő szakasz alatt:

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

ebben a részletben egy vonal konstruktort hívtunk, d3.vonal (), amely két accessort használ: x a vízszintes síkban lévő értékekhez, y pedig a függőleges tengelyhez. Itt egyszerűen rámutatunk a tömb, a dátum és a mérés legrészletesebb értékeire (ez nem az az idő, hogy aggódjunk a beágyazott csv struktúra miatt). Ha ez megtörtént, illessze be a következőket a rajz szakasz alatti sorokba:

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

ez némi magyarázatot igényel. A változó vonalak kiválaszt egy azonosítatlan számú sort az svg – ből-és azonnal megmondja a D3 – nak, hogy 3 sor lesz a szeletkészletre mutatva (a, B és C vonalak). Ezután mindegyikhez hozzáfűz egy g elemet: egy csoportosító elemet, amely a megfelelő időben megkönnyíti az életünket. A g elem mindent összegyűjt, ami egy adott diagramsorozathoz kapcsolódik (más néven egy szelet a tömbben): a vonal (a fentiekben elérési útként ábrázolva), annak adatpontjai, amelyekre az egérmutatót át tudjuk vinni, valamint a sorozatcímkék.

az első dolog, amit hozzá kell fűzni a sorokhoz (amelyek valójában 3 üres g konténerek) maguk a diagramvonalak. Hívjuk a d3-at.vonal() konstruktor az adatokat, hogy dolgozzon egy utat. Nézze meg, hogyan kell először hozzáférnünk az egyes szeletek értékeihez. Ezt aztán átadják a konstruktornak, amely szükség szerint húzza a dátumokat és a méréseket.

a módosítások mentése után a megjelenítés erre frissül:

Vonaldiagram helyett egy hegyi diagramot kaptunk

Oké, ez nem tökéletes, de hidd el, odaérünk! Alkalmazzunk néhány esztétikai javítást a diagramon, és figyeljük meg, hogyan formálódik. Adja hozzá a következőket a stílusokhoz.css:

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

a kitöltést nullára kell állítanunk, hogy az alakzatok újra vonalként jelenjenek meg. Frissítse a grafikont:

a vonalak megjelentek

mi választja el a vonaldiagramot a grafikonon összeragadt vonalak csomójától? A sorozat megkülönböztetésének képessége. Jelenleg csak az előbbi van.

kezdetnek különbséget kell tennünk a kód sorai között. Adjunk hozzá egy azonosítót minden sorosztályhoz – adjuk hozzá a következőket az előkészítő rész vonalak szakaszához:

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

ez a kis kóddarab létrehoz egy számlálót, amelyet kihasználhatunk, hogy automatikusan hozzárendeljünk egy sorazonosítót minden hozzáadott sorhoz. Hivatkozzunk a számlálóra az utak osztály tulajdonságában. Állítsa be a kódot a sorok szakaszban az osztály tulajdonság hozzáadásához:

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

és varázslatosan minden út megkapja a saját osztályát!

Path class

a vonalak saját identitást kapnak

a mi dolgunk az, hogy hivatkozzunk ezekre az osztályokra a css-ben, és minden sornak megadjuk a saját egyedi karakterét. Módosítsa a CSS Vonaldiagram szakaszát:

/* 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;}

ne feledje, hogy nem csak a színt módosítom, hanem az egyes sorok löketét is megváltoztatom. Ne feledje, hogy az emberek körülbelül 10% – ánál van bizonyos fokú színvakság, és minden tisztességes, a színek megkülönböztetése bármelyikünk számára bonyolult lehet. A színek csak keverednek, ha túl sok adatsor van, és színárnyalatuk minden monitoron másképp jelenik meg.

a változtatások alkalmazása után a vonalak egyértelműen el vannak választva a grafikonon-az alább látható módon:

a vonalak vizuálisan különböznek egymástól

most a sorozatok differenciáltak, de még mindig lehetetlen megmondani, hogy melyik melyik, hacsak nem jegyezte meg az alapul szolgáló adatokat, és elég beteg vizuális képzelőerővel rendelkezik. A sorozatfelismerés többségének támogatása érdekében azt javaslom, hogy a sorozat nevét csatoljuk a grafikon jobb oldalához. Adja hozzá a következőket a vonalak rajzszakaszához:

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; });

a kódrészlet lokalizálja az egyes sorok végét, és hozzáfűz egy szöveges elemet. A szöveg a sortól függően Serie A, Serie B vagy Serie C formátumban lesz kinyomtatva. Adja hozzá a következőket a css dokumentumhoz a sorozatcímkék beállításához:

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

a címkék csatolva vannak! Szép idők.

minden sorozat saját címkét kapott

mindannyian egyetértünk abban, hogy ez egy jóképű Vonaldiagram! Az alábbiakban beillesztettem a teljes kódot. Ne felejtse el megnézni az oktatóanyag második részét, amely két forgatókönyvet mutat be az interaktivitás hozzáadásához a diagramhoz.

Kövess engem a Twitteren további adattudományi / adatvizualizációs projektekért!

Kódminták

line_chart.html:

stílusok.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%;}

data.csv: