Die allgemeine Regel bei Verwendung einer data-join ist, dass Sie eine eins-zu-eins-Zuordnung von Daten zu Elementen möchten. Wenn Sie also zwei Reihen in Ihrem Streudiagramm haben, möchten Sie, dass zwei Containerelemente (z. B. G elements) die Serie darstellen. Da Sie derzeit nur ein data
Array haben, möchten Sie auch array.map verwenden, um die Datendarstellung in zwei parallele Arrays mit der gleichen Darstellung zu konvertieren. Auf diese Weise müssen Sie den Code nicht für jede Serie duplizieren.
Sagen Sie Ihre Daten in einer CSV-Datei dargestellt wurden für das x -Werten mit einer Spalte-Datei und mehr anderen Spalten für die y -Werten jede Serie:
x,y1,y2
5,90,22
25,30,25
45,50,80
65,55,9
85,25,95
Wenn Sie das wollen, Code, um vollständig generisch zu sein, müssen Sie zuerst die Namen der Reihe, wie ["y1", "y2"]
berechnen. (Wenn Sie der CSV-Datei eine dritte Spalte hinzugefügt haben, könnte dies ["y1", "y2", "y3"]
sein.) Sie können die Namen mit d3.keys berechnen, wodurch die benannten Eigenschaften aus einem Objekt extrahiert werden. Zum Beispiel gibt d3.keys({foo: 1, bar: 2})
["foo", "bar"]
zurück.
// Compute the series names ("y1", "y2", etc.) from the loaded CSV.
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x"; })
.sort();
Jetzt, da Sie die Seriennamen haben, können Sie ein Array von Punktarrays erstellen. Das äußere Array repräsentiert die Reihe (von denen es zwei gibt) und die inneren Arrays speichern die Datenpunkte. Sie können die Punkte gleichzeitig in eine konsistente Repräsentation konvertieren (Objekte mit den Eigenschaften x
und y
), sodass Sie den Code seriellübergreifend wiederverwenden können.
// Map the data to an array of arrays of {x, y} tuples.
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +d.x, y: +d[series]};
});
});
Hinweis: dieser Code verwendet den +
Operator die CSV-Werte in Zahlen zu zwingen. (CSV-Dateien sind nicht typisiert, daher sind sie anfänglich Zeichenfolgen.)
Nachdem Sie Ihre Daten nun einem regulären Format zugeordnet haben, können Sie G-Elemente für jede Serie erstellen und dann die Elemente für jeden Punkt einkreisen. Die resultierende SVG-Struktur wird wie folgt aussehen:
<g class="series">
<circle class="point" r="4.5" cx="1" cy="2"/>
<circle class="point" r="4.5" cx="3" cy="2"/>
…
</g>
<g class="series">
<circle class="point" r="4.5" cx="5" cy="4"/>
<circle class="point" r="4.5" cx="7" cy="6"/>
…
</g>
und den entsprechenden D3 Code:
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.style("fill", function(d, i) { return z(i); })
.selectAll(".point")
.data(function(d) { return d; })
.enter().append("circle")
.attr("class", "point")
.attr("r", 4.5)
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); });
Ich habe auch ein Stück Code hinzugefügt jede Serie eine einzigartige Farbe zuweisen, indem eine Füllstil Hinzufügen zu dem enthaltenden G-Element. Es gibt natürlich viele verschiedene Möglichkeiten, dies zu tun. (Vielleicht möchten Sie zum Beispiel die Farbe für jede Serie präzisieren.) Ich habe auch den Code weggelassen, der die Domänen Ihrer x und y Skalen berechnet (und auch die Achsen rendert), aber wenn Sie möchten, das gesamte Arbeitsbeispiel sehen:
fast ein Tutorial ... diese und die anderen ähnlichen Fragen, die durch so lange Antworten von Mike Bostock beantwortet wurden, sollten in die FAQ gestellt werden – paxRoman