2012-07-26 13 views
12

Tüm d3 eğiticileri, dizideki her nesne için bir nokta çizdikleri nesneler dizisinde düzenlenmiş verileri kullandım. Verilen aşağıdaki yapısındaki veriler:d3.js aynı kaynaktaki verileri kullanarak aynı grafikte iki dağılım çizebilir mi?

data = [ 
    {id: 1, x: 4, y: 10, type: 1}, 
    {id: 2, x: 5, y: 20, type: 2} 
    ... 
] 

x ve y değerleri, bir dağılım grafiğini yapmak için kullanılır. Her bir noktanın rengini değiştirmek için type parametresi kullanılır. Örnek için şu jsfiddle'a bakın: http://jsfiddle.net/uxbHv/

Ne yazık ki farklı bir veri yapısına sahibim ve her bir nesne için iki veri noktası çizerek aynı grafiği nasıl oluşturacağımı anlayamıyorum. İşte bazı örnek veriler: Ben yVar1 veya yVar2 karşı bireysel olarak xVar grafiğini çizebilirsiniz

dataSet = [ 
    {xVar: 5, yVar1: 90, yVar2: 22}, 
    {xVar: 25, yVar1: 30, yVar2: 25}, 
    {xVar: 45, yVar1: 50, yVar2: 80}, 
    {xVar: 65, yVar1: 55, yVar2: 9}, 
    {xVar: 85, yVar1: 25, yVar2: 95} 
] 

ama aynı grafikte hem nasıl bilemiyorum: Her veri için http://jsfiddle.net/634QG/

cevap

30

bir data-join kullanarak genel kural elemanları için verilerden bir bire bir eşleme istememizdir. Dolayısıyla, dağılım grafiğinizde iki diziniz varsa, diziyi temsil edecek iki kapsayıcı öğenin (örneğin, G elements) olmasını istersiniz. Şu anda yalnızca bir tane data diziniz olduğundan, aynı gösterime sahip iki paralel diziye veri temsilini dönüştürmek için array.map'u da kullanmak istersiniz. Bu şekilde, her seri için kodu çoğaltmanız gerekmez.

için bir x-değerlerinin için sütun ve birden diğer sütunlara dosyası veri CSV temsil edilmiştir Say y her serinin-değerleri:

x,y1,y2 
5,90,22 
25,30,25 
45,50,80 
65,55,9 
85,25,95 

İsterseniz Kod tamamen jenerik olacak, ilk olarak ["y1", "y2"] gibi dizilerin isimlerini hesaplamanız gerekir. (CSV dosyasına üçüncü bir sütun eklediyseniz, ["y1", "y2", "y3"] olabilir.) Adları, bir nesneden adlandırılmış özellikleri ayıklar olan d3.keys kullanarak hesaplayabilirsiniz. Örneğin, d3.keys({foo: 1, bar: 2}), ["foo", "bar"]'u döndürür.

Artık dizi adlarına sahip olduğunuzdan, bir dizi nokta dizisi oluşturabilirsiniz. Dış dizi (iki tane var) diziyi temsil eder ve iç diziler veri noktalarını depolar. Aynı anda kodları tutarlı bir gösterime (x ve y özelliklerine sahip nesneler) dönüştürebilirsiniz, böylece kodları dizi genelinde yeniden kullanabilirsiniz.

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

Not bu kod numaralarına CSV değerleri zorlamak için + operatörünü kullanır. (CSV dosyaları yazılmamış, bu nedenle başlangıçta dizelerdir.

Verilerinizi düzenli bir biçimde eşlediğinizden, her bir seri için G öğeleri oluşturabilir ve ardından her bir nokta için öğeleri daire içine alabilirsiniz. Oluşan SVG yapısı aşağıdaki gibi görünecektir:

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

Ve tekabül D3 kodu:

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

Ben de bir dolgu stilini ekleyerek her serisi benzersiz bir renk atamak için kod biraz ekledik içeren G elemanına. Elbette bunu yapmak için birçok farklı yol var. (Örneğin, her bir dizinin rengi hakkında daha spesifik olmak isteyebilirsiniz.) Ayrıca, x ve y ölçeklerinin etki alanlarını hesaplayan kodun dışında kaldım (ayrıca eksenleri oluştururken), ancak tüm çalışma örneği görmek istiyorsanız: çözüm

+0

Neredeyse bir öğretici ... Bu ve Mike Bostock tarafından yapılan uzun cevaplarla cevaplanan diğer benzer sorular SSS'ye konmalıdır. – paxRoman

4

Yeri iki daire Tek bir svg:g öğesinin içine gelin. Bu, veriler için veri için bire bir eşleme üretir, ancak yine de iki farklı nokta göstermenizi sağlar.

var nodeEnter = vis1.selectAll("circle") 
     .data(dataSet) 
     .enter() 
     .insert("svg:g"); 

nodeEnter.insert("svg:circle") 
      .attr("cx", function (d) { return 100 - d.xVar}) 
      .attr("cy", function (d) { return 100 - d.yVar1}) 
      .attr("r", 2) 
      .style("fill", "green"); 

nodeEnter.insert("svg:circle") 
      .attr("cx", function (d) { return 100 - d.xVar}) 
      .attr("cy", function (d) { return 100 - d.yVar2}) 
      .attr("r", 2) 
      .style("fill", "blue"); 

JSFiddle çalışmak.

+0

teşekkürler! geri jsfiddle için .... Ben bu statik verilerle nasıl çalıştığını görmek, ancak geçişler eklemek zor ve çıkar eğer şimdi merak ediyorum ... –

+0

Bu (şimdi) işe yarayabilir, ama ben şiddetle bu Desen önüne geçecek API bu şekilde çalışmak üzere tasarlanmamıştır. Bir veri birleştirmeyi kullanırken, her zaman veri ve öğeler arasında bire bir eşleme olması gerekir. Giriş seçimine iki kez ekleme veya ekleme, API'nin kötüye kullanılmasıdır. Bu durumda doğru çözüm, iki “vis” unsuru yaratmak ve verileri tutarlı bir temsile sahip iki paralel diziye eşlemektir. – mbostock

+0

@mbostock Bu daha iyi bir yaklaşım mı? http://jsfiddle.net/634QG/3/ –

İlgili konular