Javascript 聚合数据上的dc.js表

Javascript 聚合数据上的dc.js表,javascript,dc.js,Javascript,Dc.js,我一直在用自己的数据从这里复制代码,试图了解dc.js [ {"grade": 8, "category": "Math", "rating": 4}, {"grade": 8, "category": "English", "rating": 3}, {"grade": 8, "category": "Math", "rating": 1}, {"grade": 8, "category": "Math", "rating": 3}, {"grade": 8, "category": "Sci

我一直在用自己的数据从这里复制代码,试图了解dc.js

[
{"grade": 8, "category": "Math", "rating": 4},
{"grade": 8, "category": "English", "rating": 3},
{"grade": 8, "category": "Math", "rating": 1},
{"grade": 8, "category": "Math", "rating": 3},
{"grade": 8, "category": "Science", "rating": 1},
{"grade": 9, "category": "Science", "rating": 2},
{"grade": 9, "category": "Science", "rating": 5},
{"grade": 9, "category": "English", "rating": 5}
]
结果是一个如下表:

8   English 3
8   Math    2.67
8   Science 1
9   English 5
9   Science 3.5
我已经把这些放在一起了

        var chart = dc.dataTable("#test");

        d3.json("test.json", function(error, experiments) {

          console.log(experiments);

          var ndx              = crossfilter(experiments),
          exptDimension    = ndx.dimension(function(d) {return +d.grade;}),
          groupedDimension = exptDimension.group().reduce(
            function (p, v) {
              ++p.number;
              p.total += +v.rating;
              p.category = v.category;
              p.grade = v.grade;
              p.avg = (p.total / p.number).toFixed(2);
              console.log(p);
              return p;
            },
            function (p, v) {
              --p.number;
              p.total -= +v.rating;
              p.category = v.category;
              p.grade = v.grade;
              p.avg = (p.number == 0) ? 0 : Math.round(p.total / p.number).toFixed(2);
              return p;
            },
            function () {
              return {number: 0, total: 0, avg: 0, category:"", grade:"", }
            }),
          rank = function (p) { return "rank" };

          chart
          .width(768)
          .height(480)
          .dimension(groupedDimension)
          .group(rank)
          .columns([function (d) { console.log(d); return d.value.grade },
            function (d) { return d.value.category },
            function (d) { return d.value.avg }])
          .sortBy(function (d) { return d.value.avg })
          .order(d3.descending)
          chart.render();
        });
因此:

9   English 4.00
8   Science 2.40
我觉得我错过了一些非常简单的事情。有人对如何进行有什么建议吗


谢谢

是的,很简单——或者说基本上很简单。有一个隐含的要求,即您希望同时按年级和类别分组,而您只是按年级分组。您的reduce函数在这种情况下没有多大意义,因为

          p.category = v.category;
假设每个年级只有一个类别。但是如果你忽略这一点,答案是“正确的”,9年级学生的平均分数是4,8年级学生的平均分数是2.4

要同时按等级和类别分组,可以指定一个标注键,其中包含两个值:

      exptDimension    = ndx.dimension(function(d) {return d.category+'/'+d.grade;}),
这将构造一个包含两个值的字符串。有些人只是在这里创建一个数组键,但我不喜欢这样,因为它会对字符串进行一些隐式转换,这稍微慢一点

这很简单,但它只按平均评级下单:

9   English 5.00
9   Science 3.50
8   English 3.00
8   Math    2.67
8   Science 1.00

另一个隐含的要求是,您希望按等级按升序排序,平均评分按降序排序。这有点难,因为这意味着您需要指定一个键来编码两个相反的顺序

这里有一种方法:

      .sortBy(function (d) { return (20-d.value.grade)*1000 + d.value.avg; })
嗯。哇!这将是一个有趣的保持,但我不知道一个更好的方法来做到这一点。它创建了一个排序键,其中grade是高度负加权的,avg是弱正加权的,当与
d3.descending
结合使用时,将执行您想要的操作

最终结果:

8   English 3.00
8   Math    2.67
8   Science 1.00
9   English 5.00
9   Science 3.50