2017-02-13 31 views
0

我想要查看數據集以查看穿山甲交易中的主要參與者。我希望每個國家都是y軸上的分類比例的一部分,x軸是日期,我希望每個交易實例都表示爲一個圓圈,其中x是它發生的日期,y是該特定國家的位置,r是迄今累計的實例數(在我的數據中表示爲r)。基本上我的數據是從2010年到2016年,包括穿山甲輸入或輸出的國家名稱,計數(到目前爲止的累積交易實例)和日期(年 - 月 - 日)。 下面是我的數據,我存儲在變量貿易的一部分:使用d3.nest創建的數據集不能正確繪圖

[{"date":"2010-10-22","country":"Thailand","rank":4,"count":1},{"date":"2010-10-28","country":"Malaysia","rank":2,"count":1},{"date":"2010-11-8","country":"Thailand","rank":4,"count":2},{"date":"2010-11-18","country":"Nepal","rank":7,"count":1},{"date":"2010-11-22","country":"China","rank":5,"count":1},{"date":"2010-11-22","country":"China","rank":5,"count":2},{"date":"2010-11-27","country":"India","rank":1,"count":1},{"date":"2010-11-28","country":"India","rank":1,"count":2},{"date":"2010-11-28","country":"India","rank":1,"count":3},{"date":"2010-11-30","country":"India","rank":1,"count":4},{"date":"2010-12-17","country":"Malaysia","rank":2,"count":2},{"date":"2010-12-22","country":"Vietnam","rank":3,"count":1},{"date":"2011-01-3","country":"Nepal","rank":7,"count":2},{"date":"2011-02-12","country":"Myanmar","rank":8,"count":1},{"date":"2011-02-25","country":"Malaysia","rank":2,"count":3},{"date":"2011-02-26","country":"Malaysia","rank":2,"count":4},{"date":"2011-03-2","country":"South Africa","rank":18,"count":1},{"date":"2011-03-2","country":"Rwanda","rank":35,"count":1},{"date":"2011-03-2","country":"Mozambique","rank":22,"count":1},{"date":"2011-03-2","country":"Kenya","rank":12,"count":1},{"date":"2011-03-3","country":"China","rank":5,"count":3},{"date":"2011-02-21","country":"Vietnam","rank":3,"count":2},{"date":"2011-03-24","country":"Malaysia","rank":2,"count":5},{"date":"2011-04-4","country":"Malaysia","rank":2,"count":6},{"date":"2011-03-25","country":"India","rank":1,"count":5},{"date":"2011-03-26","country":"Malaysia","rank":2,"count":7},{"date":"2011-04-2","country":"Nepal","rank":7,"count":3},{"date":"2011-04-20","country":"Thailand","rank":4,"count":3},{"date":"2011-05-11","country":"China","rank":5,"count":4},{"date":"2011-05-11","country":"China","rank":5,"count":5},{"date":"2011-05-26","country":"Indonesia","rank":6,"count":1},{"date":"2011-05-26","country":"India","rank":1,"count":6},{"date":"2011-05-29","country":"Indonesia","rank":6,"count":2},{"date":"2011-06-6","country":"India","rank":1,"count":7},{"date":"2011-06-7","country":"Mozambique","rank":22,"count":2},{"date":"2011-06-5","country":"India","rank":1,"count":8},{"date":"2011-06-12","country":"Malaysia","rank":2,"count":8},{"date":"2011-06-13","country":"Singapore","rank":21,"count":1},{"date":"2011-06-14","country":"Malaysia","rank":2,"count":9},{"date":"2011-06-17","country":"India","rank":1,"count":9},{"date":"2011-06-19","country":"India","rank":1,"count":10},{"date":"2011-06-26","country":"Thailand","rank":4,"count":4},{"date":"2011-06-30","country":"India","rank":1,"count":11},{"date":"2011-07-4","country":"Malaysia","rank":2,"count":10},{"date":"2011-07-5","country":"Zimbabwe","rank":14,"count":1},{"date":"2011-07-12","country":"Indonesia","rank":6,"count":3},{"date":"2011-07-18","country":"Indonesia","rank":6,"count":4},{"date":"2011-07-27","country":"Nepal","rank":7,"count":4},{"date":"2011-08-16","country":"Nepal","rank":7,"count":5},{"date":"2011-08-19","country":"Namibia","rank":33,"count":1},{"date":"2011-08-23","country":"India","rank":1,"count":12},{"date":"2010-09-17","country":"Myanmar","rank":8,"count":2},{"date":"2011-09-1","country":"Zimbabwe","rank":14,"count":2},{"date":"2011-09-13","country":"Indonesia","rank":6,"count":5},{"date":"2011-09-13","country":"Malaysia","rank":2,"count":11},{"date":"2011-09-13","country":"Myanmar","rank":8,"count":3},{"date":"2011-09-21","country":"Malaysia","rank":2,"count":12},{"date":"2011-09-26","country":"Thailand","rank":4,"count":5},{"date":"2011-09-30","country":"Indonesia","rank":6,"count":6},{"date":"2011-10-1","country":"Sri Lanka","rank":19,"count":1},{"date":"2011-10-6","country":"India","rank":1,"count":13},{"date":"2011-10-7","country":"India","rank":1,"count":14},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":7},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":8},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":9},{"date":"2011-10-22","country":"India","rank":1,"count":15},{"date":"2011-10-24","country":"India","rank":1,"count":16},{"date":"2011-11-28","country":"United States","rank":32,"count":1},{"date":"2011-12-15","country":"Vietnam","rank":3,"count":3},{"date":"2011-12-27","country":"Thailand","rank":4,"count":6},{"date":"2012-01-4","country":"Philippines","rank":15,"count":1},{"date":"2012-01-5","country":"Kenya","rank":12,"count":2},{"date":"2012-01-6","country":"Philippines","rank":15,"count":2},{"date":"2012-01-17","country":"Philippines","rank":15,"count":3},{"date":"2012-01-24","country":"China","rank":5,"count":6},{"date":"2012-02-22","country":"Malaysia","rank":2,"count":13},{"date":"2012-03-1","country":"Malaysia","rank":2,"count":14},{"date":"2012-03-19","country":"Pakistan","rank":11,"count":1},{"date":"2012-03-21","country":"Malaysia","rank":2,"count":15},{"date":"2012-03-23","country":"Vietnam","rank":3,"count":4},{"date":"2012-04-27","country":"Vietnam","rank":3,"count":5},{"date":"2012-04-23","country":"Belgium","rank":31,"count":1},{"date":"2012-06-7","country":"Thailand","rank":4,"count":7},{"date":"2012-06-7","country":"Thailand","rank":4,"count":8}]; 

這裏是我的代碼:

var margin = {left:120, top:20, right:0, bottom:50}; 
    var width = 1000; 
    var height = 800; 


    var data=trade; 


    var tradeByCountry = d3.nest() 
     .key(function(d) { return d.country; }) 
     .entries(trade); 

     console.log(tradeByCountry); 

     tradeByCountry.forEach(function(country){ 
     country['number']=country.values.length; 
     console.log(country); 
     }); 


     var country_colors = ["#393b79","#5254a3", '#6b6ecf', '#9c9ede', '#637939', '#8ca252','#b5cf6b','#cedb9c', 
     '#8c6d31','#bd9e39','#e7ba52','#e7cb94','#843c39','#ad494a','#d6616b','#e7969c','#7b4173','#a55194', 
     '#ce6dbd','#de9ed6', '#9467bd', '#c5b0d5','#3182bd', '#6baed6','#17becf','#9edae5','#e6550d','#fd8d3c','#fdae6b', 
     '#31a354','#74c476','#a1d99b','#d62728','#ff9896','#7f7f7f','#c7c7c7']; 


     var colors = d3.scale.ordinal() 
        .domain(d3.range(tradeByCountry.length)) 
        .range(country_colors); 




     tradeByCountry.sort(function(x, y){ 
      return d3.descending(x.number, y.number); 
     }) 


     var countriesArray = []; 


     tradeByCountry.forEach(function(country){ 
      countriesArray.push(country.key); 

     }); 

     console.log(countriesArray); 


     var x = d3.time.scale() 
     .rangeRound([0, width]); 

     var y = d3.scale.linear() 
      .range([height, 0]); 


     var timeFormat = d3.time.format("%Y-%m-%d"); 

     x.domain([timeFormat.parse('2010-10-22'),timeFormat.parse('2016-12-30')]); 
     y.domain(countriesArray); 


     var xAxis = d3.svg.axis() 
      .scale(x) 
      .orient("bottom"); 

     var yAxis = d3.svg.axis() 
      .scale(y) 
      .orient("left"); 

     var svg = d3.select("body").append("svg") 
       .attr("width", width + margin.left + margin.right) 
       .attr("height", height + margin.top + margin.bottom) 
       .append("g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

      svg.append("g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0," + height + ")") 
       .call(xAxis) 
      .append("text") 
       .attr("class", "label") 
       .attr("x", width) 
       .attr("y", -6) 
       .style("text-anchor", "end") 
       .text("date"); 

      svg.append("g") 
       .attr("class", "y axis") 
       .call(yAxis) 
      .append("text") 
       .attr("class", "label") 
       .attr("transform", "translate(35,-25)") 
       .attr("y", 6) 
       .attr("dy", ".71em") 
       .style("text-anchor", "end") 
       .text("countries"); 



      svg.selectAll(".dot") 
      .data(tradeByCountry) 
      .enter().append("circle") 
       .attr("class", "dot") 
       .attr("r", 7) 
       .attr("cx", function(d) { return 0; }) 
       .attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; }) 
       .style("fill", function(d,i) { return colors(i); }); 


      svg.selectAll("text.labels") 
       .data(tradeByCountry) 
       .enter() 
       .append("text") 
       .text(function(d) {return d.key}) 
       .attr("x", 0) 
       .attr("y", function(d,i) { return (height/tradeByCountry.length)*i; }) 
       .attr("transform", "translate(-120,5)") 
       .attr("fill",function(d,i) { return colors(i); }); 


       svg.selectAll('.line') 
       .data(tradeByCountry) 
       .enter().append('line') 
       .attr("x1", 0)  // x position of the first end of the line 
       .attr("y1",function(d,i) { return (height/tradeByCountry.length)*i; }) 
       .attr("x2", width)  // x position of the second end of the line 
       .attr("y2", function(d,i) { return (height/tradeByCountry.length)*i; }) 
       .style("stroke",function(d,i) { return colors(i); }) 
       .attr("id", function(d){return d.key}); 



      //PROBLEM HERE!!!!!!!!!!! 
       var g = svg 
       .selectAll("g") 
       .data(tradeByCountry) 
       .enter().append("g")   
       .selectAll(".dot") 
       .data(function(d) {return d.values;}) 
       .enter().append("circle") 
       .attr("id", function(d){ return d.count;}) 
       .attr("r", function(d){return d.count;}) 
       .attr("cx", function(d,i) { console.log (d.date);return (x(timeFormat.parse(d.date))); }) 
       .attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; }) 
       .style("fill", function(d,i) { return colors(i); }); 

我有專門在我的代碼的最後部分的麻煩,在那裏我無法得到所有的圈子繪製,並沒有在正確的r,因爲我想隨着時間的推移增加一個國家,而不是似乎r是根據國家不同:

enter image description here

回答

1

有兩件事,首先在你的例子.selectAll("g")中,你標記爲有錯誤的地方是在座標軸中拾取了g個元素,所以前幾個國家沒有得到他們的數據顯示。這在你的屏幕截圖中似乎不是這種情況,但是由於你發佈了代碼,所以發生了這種情況,所以我只是將那些g.country類合格。

第二件事情,並且是什麼原因導致你的具體問題是這一行:

.attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; }) 

我猜你以爲索引變量i這裏仍綁在tradeByCountry陣列,它會一直selectAll("g.country").data(tradebyCountry)之後,但現在我們已經爲每個國家/地區的數據在d.values上做出了嵌套選擇.selectAll(".dot"),因此i正在爲這些值列表建立索引。因此,上面這行代碼將採用每個國家的值並將它們全部垂直分開,始終從最上面一行開始 - 實際上,您希望它們位於同一行上,並且按國家/地區分隔。

What you wanted (I = India, M = Malaysia, T = Thailand) 
I--- I0  I1  I2 
M---  M0M1      M2 
T---   T0 T1  T2 

What you were getting 
I--- I0 M0 T0 
M---  M1 I1 T1 
T---      I2 T2  M2 

這也被事實.attr隱藏(「填充」)也有​​同樣的錯誤,所以各行上的顏色是一致的(我用d.rank,而不是修復它)。

解決方案1:爲了確保值停留在同一個正確的線路上使用i你做的嵌套的選擇之前,所以它仍然是指國家是這樣,這將是正確的量相互抵消g元素:

.attr("transform", function(d,i) { 
     return "translate(0,"+(height/tradeByCountry.length)*i+")"; 
    }) 

和簡單的設置cy成爲您添加到這個g元素都爲零,他們將全部在一條直線上(和右邊線)在這裏的問題

全部代碼!階段:

var g = svg 
        .selectAll("g.country") 
        .data(tradeByCountry) 
        .enter().append("g") 
        .attr("class", "country") 
        .attr("transform", function(d,i) { 
         return "translate(0,"+(height/tradeByCountry.length)*i+")"; 
         }) 
        .selectAll(".dot") 
        .data(function(d) {return d.values;}) 
        .enter().append("circle") 
        .attr("class", "dot") 
        .attr("id", function(d){ return d.country+"_"+d.date+"_"+d.count;}) 
        .attr("r", function(d){ return d.count;}) 
        .attr("cx", function(d,i) { console.log (d.date);return (x(timeFormat.parse(d.date))); }) 
        .attr("cy", function(d,i) { return 0; }) 
        .style("fill", function(d,i) { return colors(d.rank); }); 

http://jsfiddle.net/d4typ567/1/

解決方案2:這也是該D3保持用於嵌套選擇父索引變量(通常表示ii),可以傳遞到最D3 .attr和.style功能的情況下,所以你可以用.attr("cy", function(d,i, ii) { return (height/tradeByCountry.length)*ii; })來代替,但是抵消g元素只有1次操作,而這是爲每個圓圈完成的。請記住爲顏色(填充)功能做同樣的事情。

+0

謝謝!我明白d3.nest()現在如何運作更多! – jhjanicki

+0

這裏是最終的可視化:https://jhjanicki.github.io/pangolin-trade/ – jhjanicki