D3.js 使用d3.nest创建的数据集绘制不正确

D3.js 使用d3.nest创建的数据集绘制不正确,d3.js,D3.js,我试图将一个数据集可视化,以查看穿山甲交易中的主要参与者。我希望每个国家都是y轴上分类量表的一部分,x轴是日期,我希望每个贸易实例都表示为一个圆圈,x是它发生的日期,y是该特定国家的位置,r是迄今为止在我的数据中累积的实例数,表示为r。基本上,我的数据是从2010年到2016年,包括穿山甲进口或出口的国家名称、截至该日期的累计贸易实例数以及yyyy-mm-dd日期。 以下是我存储在变量交易中的部分数据: [{"date":"2010-10-22","country":"Thailand","ra

我试图将一个数据集可视化,以查看穿山甲交易中的主要参与者。我希望每个国家都是y轴上分类量表的一部分,x轴是日期,我希望每个贸易实例都表示为一个圆圈,x是它发生的日期,y是该特定国家的位置,r是迄今为止在我的数据中累积的实例数,表示为r。基本上,我的数据是从2010年到2016年,包括穿山甲进口或出口的国家名称、截至该日期的累计贸易实例数以及yyyy-mm-dd日期。 以下是我存储在变量交易中的部分数据:

[{"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随着一个国家的贸易积累而增加,相反,r似乎因国家而异:


有两件事,首先是在你的例子中。在你标记为有错误的点选择Allg,因为它在轴上拾取g元素,所以前几个国家没有显示它们的数据。在你的屏幕截图中似乎不是这样,但考虑到你发布的代码,这种情况发生了,所以我只是用.country类限定了那些gs

第二件事,是什么导致了您的具体问题是这一行:

.attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; })  
我猜您认为这里的索引变量I仍然与tradeByCountry数组相关联,在选择AllG.country.datatradebyCountry之后,它会是这个数组,但此时我们已经做了一个嵌套选择。为每个国家的数据在d.values上选择All.dot,所以我现在正在为这些值列表编制索引。因此,上面的代码行将获取每个国家的值,并将它们垂直分开,始终从第一行开始-实际上,您希望它们位于同一行,只是按国家分开

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
这也被事实掩盖了。attrfill也有同样的错误,所以每行的颜色都是一致的,我用d.rank来修正它

解决方案1:要确保值保持在同一正确行上,请在进行嵌套选择之前使用i,使其仍然指向这样的国家/地区,这将以正确的数量偏移每个g元素:

  .attr("transform", function(d,i) {
        return "translate(0,"+(height/tradeByCountry.length)*i+")";
   })
简单地把你加在g元素上的所有东西的cy设为零,它们都在一条直线上,在右边

完整的代码在这里的问题!阶段:

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

解决方案2:d3也为嵌套选择维护一个父索引变量,通常表示为ii,可以传递到大多数d3.attr和.style函数中,因此可以改为.attrcy、functiond、i、ii{return height/tradeByCountry.length*ii;},但偏移g元素只需1次操作,而这是对每个圆进行的。记得对颜色填充功能也要这样做。

谢谢!我现在更了解d3.nest的工作原理了!