dc.js table 聚合数据
dc.js table on aggregated data
我一直在尝试通过使用我自己的数据从此处 https://github.com/dc-js/dc.js/blob/develop/web/examples/table-on-aggregated-data.html 复制代码来解决 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}
]
结果是这样的 table:
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;
假设每个年级只有一个类别。但如果你忽略它,答案有点像 "correct",因为 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
http://jsfiddle.net/gordonwoodhull/5sbdvtqv/2/
另一个隐含的要求是您希望按等级升序排列,平均评分按降序排列。这有点困难,因为这意味着您需要指定一个编码两个相反顺序的密钥。
这是一种方法:
.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
我一直在尝试通过使用我自己的数据从此处 https://github.com/dc-js/dc.js/blob/develop/web/examples/table-on-aggregated-data.html 复制代码来解决 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}
]
结果是这样的 table:
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;
假设每个年级只有一个类别。但如果你忽略它,答案有点像 "correct",因为 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
http://jsfiddle.net/gordonwoodhull/5sbdvtqv/2/
另一个隐含的要求是您希望按等级升序排列,平均评分按降序排列。这有点困难,因为这意味着您需要指定一个编码两个相反顺序的密钥。
这是一种方法:
.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