Datendarstellung mit D3.js und jQuery-DataTables

Verwenden derselben Datenquelle für beide Darstellungen

Ich war – vergeblich – auf der Suche nach etwas Beispielcode, wie man ein Datenset sowohl als Tabelle (gepimpt mit DataTables) als auch als Kurve mit D3.js darstellen kann. Ich wollte die Daten nicht in zwei unterschiedlichen Formaten exportieren, das spart zum einen Code und zum anderen Ladezeit (die Daten müssen nur einmal geladen und können anschließend gecached werden). Da meine Suche erfolglos blieb, habe ich mich selbst um eine Lösung bemüht, und damit spätere Suchende fündig werden, verwegige ich sie hier :-)

Tabelle mit DataTables befüllen

Das Standardformat für Daten ist hier ein JSON-Dokument, das neben weiterer Konfiguration auch ein data-Element beinhaltet. Dieses enthält als Array von Arrays die Daten der einzelnen Tabellenzeilen. DataTables kann die Überschriften einer Tabelle ebenfalls generieren, dazu werden die Daten im Feld columns abgelegt. Die verwendeten Testdaten 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 DataTables-Tabelle automatisch generieren:

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

Soweit also alles nach DataTables-Standard. Dieselben Daten lassen sich aber auch für D3.js nutzen – stay tuned :-)

Kurvendarstellung mit D3.js

Als Grundlage diente mir dieses D3.js-Beispiel, an dem ich mich code-technisch großzügig bedient habe. Die Daten können hier nicht 1:1 übernommen werden: Hier werden die Daten „spaltenweise“ benötigt, also alle ersten Elemente der Datenarrays, dann alle zweiten Elemente, …, die dann jeweils eine Kurve ergeben. Obendrein muß der erste Eintrag jedes Arrays für die Beschriftung der X-Achse benutzt werden.

Deshalb habe ich mir zunächst die Einträge der X-Achse (die erste Spalte jeder Tabellenzeile) im separaten Array xAxisEntries und die Namen der Kurven (die Spaltenüberschriften aus DataTables) im Array dataSets zurechtgelegt. Beim Erzeugen der einzelnen Kurven erlaubt D3.js das Hinterlegen entsprechender Lookup-Funktionen, in denen dann der Lookup in die JSON-Daten erfolgt. Die interessanten Codestellen sehen folgendermaß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 Endergebnis

Das Ergebnis meines Experiments sieht folgendermaßen aus:

Als Download-Paket habe ich eine funktionierende Beispielseite mit allen nötigen JS-Dateien zusammengestellt. Viel Spaß beim Basteln!