2017-02-13 60 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