Datendarstellung mit D3.js und jQuery-DataTables

Verwenden derselben Datenquelle für beide Darstellungen

Ich war – ver­geb­lich – auf der Suche nach etwas Bei­spiel­code, wie man ein Da­ten­set so­wohl als Ta­bel­le (ge­pimpt mit Data­Tables) als auch als Kurve mit D3.js dar­stel­len kann. Ich woll­te die Daten nicht in zwei un­ter­schied­li­chen For­ma­ten ex­por­tie­ren, das spart zum einen Code und zum an­de­ren La­de­zeit (die Daten müs­sen nur ein­mal ge­la­den und kön­nen an­schlie­ßend ge­ca­ched wer­den). Da meine Suche er­folg­los blieb, habe ich mich selbst um eine Lö­sung be­müht, und damit spä­te­re Su­chen­de fün­dig wer­den, ver­we­gi­ge ich sie hier :-)

Ta­bel­le mit Data­Tables be­fül­len

Das Stan­dard­for­mat für Daten ist hier ein JSON-Do­ku­ment, das neben wei­te­rer Kon­fi­gu­ra­ti­on auch ein data-Ele­ment be­inhal­tet. Die­ses ent­hält als Array von Ar­rays die Daten der ein­zel­nen Ta­bel­len­zei­len. Data­Tables kann die Über­schrif­ten einer Ta­bel­le eben­falls ge­ne­rie­ren, dazu wer­den die Daten im Feld columns ab­ge­legt. Die ver­wen­de­ten Test­da­ten sehen daher so aus:

{
  "columns": [
      { "title": "Pfirsich" },
      { "title": "Ananas" },
      { "title": "Kirsche" },
      { "title": "Aprikose" }
    ],
  "data": [
    ["01/2013",20,16,10,5],
    // ...
    ["12/2013",22,20,18,10]
  ]
}

Damit kann ich meine Data­Tables-Ta­bel­le au­to­ma­tisch ge­ne­rie­ren:

<table id="testtable">
</table>
<script>
    $.getJSON('data.json', function(data) {
        $('#testtable').dataTable(data);
    });
</script>

So­weit also alles nach Data­Tables-Stan­dard. Die­sel­ben Daten las­sen sich aber auch für D3.​js nut­zen – stay tuned :-)

Kur­ven­dar­stel­lung mit D3.​js

Als Grund­la­ge dien­te mir die­ses D3.​js-Bei­spiel, an dem ich mich code-tech­nisch gro­ßzü­gig be­dient habe. Die Daten kön­nen hier nicht 1:1 über­nom­men wer­den: Hier wer­den die Daten „spal­ten­wei­se“ be­nö­tigt, also alle ers­ten Ele­men­te der Da­ten­ar­rays, dann alle zwei­ten Ele­men­te, …, die dann je­weils eine Kurve er­ge­ben. Oben­drein muß der erste Ein­trag jedes Ar­rays für die Be­schrif­tung der X-Ach­se be­nutzt wer­den.

Des­halb habe ich mir zu­nächst die Ein­trä­ge der X-Ach­se (die erste Spal­te jeder Ta­bel­len­zei­le) im se­pa­ra­ten Array xAxisEntries und die Namen der Kur­ven (die Spal­ten­über­schrif­ten aus Data­Tables) im Array dataSets zu­recht­ge­legt. Beim Er­zeu­gen der ein­zel­nen Kur­ven er­laubt D3.​js das Hin­ter­le­gen ent­spre­chen­der Look­up-Funk­tio­nen, in denen dann der Look­up in die JSON-Da­ten er­folgt. Die in­ter­es­san­ten Code­stel­len sehen fol­gen­der­ma­ßen aus:

d3.json("data.json", function(error, jsonData) {
    var parseDate = d3.time.format("%m/%Y").parse;
    var xAxisEntries = jsonData.data.map(function(arr) { return parseDate(arr[0]); });
    var dataSets = jsonData.columns.map(function(col) { return col.title; });

    // ...

    for (var dataSet=0; dataSet<dataSets.length; dataSet++) {
        var line = d3.svg.line()
                .x(function(xVal) { return x(xAxisEntries[xVal]); })
                .y(function(xVal) { return y(jsonData.data[xVal][dataSet+1]); });

        svg.append("path")
                .datum(d3.range(0, xAxisEntries.length))
                .attr("d", line);
    }
});

Das End­er­geb­nis

Das Er­geb­nis mei­nes Ex­pe­ri­ments sieht fol­gen­der­ma­ßen aus:

Als Down­load-Pa­ket habe ich eine funk­tio­nie­ren­de Bei­spiel­sei­te mit allen nö­ti­gen JS-Da­tei­en zu­sam­men­ge­stellt. Viel Spaß beim Bas­teln!