dc.js - 为什么我的饼图在使用 dc.js 和 crossfilter.js 中的堆叠条形图进行过滤时显示不正确的组?

标签 dc.js crossfilter

当我单击 dc.js 堆叠条形图时,同一页面上其他位置的饼图未显示正确的组。

我是 dc.js 的新手,因此我创建了一个简单的数据集来演示我需要的功能:Alice 和 Bob 撰写有关水果的文章,并使用单个标签标记每篇文章。我将这些数据绘制成图表如下:

  • 显示每天文章数量的折线图
  • 饼图显示使用的每个标签的总数
  • 显示作者使用的标签数量的堆叠条形图

数据集如下:

rawData = [
{"ID":"00000001","User":"Alice","Date":"20/02/2019","Tag":"apple"},
{"ID":"00000002","User":"Bob","Date":"17/02/2019","Tag":"dragonfruit"},
{"ID":"00000003","User":"Alice","Date":"21/02/2019","Tag":"banana"},
{"ID":"00000004","User":"Alice","Date":"22/02/2019","Tag":"cherry"},
{"ID":"00000005","User":"Bob","Date":"23/02/2019","Tag":"cherry"},
];

示例性 JSFiddle 位于:https://jsfiddle.net/hv8sw6km/和下面的代码片段:

/* Prepare data */

rawData = [
{"ID":"00000001","User":"Alice","Date":"20/02/2019","Tag":"apple"},
{"ID":"00000002","User":"Bob","Date":"17/02/2019","Tag":"dragonfruit"},
{"ID":"00000003","User":"Alice","Date":"21/02/2019","Tag":"banana"},
{"ID":"00000004","User":"Alice","Date":"22/02/2019","Tag":"cherry"},
{"ID":"00000005","User":"Bob","Date":"23/02/2019","Tag":"cherry"},
];

var data = [];

var parseDate = d3.timeParse("%d/%m/%Y");
rawData.forEach(function(d) {
	d.Date = parseDate(d.Date);
	data.push(d);
});

var ndx = crossfilter(data);

/* Set up dimensions, groups etc. */

var dateDim = ndx.dimension(function(d) {return d.Date;});
var dateGrp = dateDim.group();

var tagsDim = ndx.dimension(function(d) {return d.Tag;});
var tagsGrp = tagsDim.group();

var authorDim = ndx.dimension(function(d) { return d.User; });
/* Following stacked bar chart example at
   https://dc-js.github.io/dc.js/examples/stacked-bar.html
   adapted for context. */
var authorGrp = authorDim.group().reduce(
	function reduceAdd(p,v) {
		p[v.Tag] = (p[v.Tag] || 0) + 1;
		p.total += 1;
		return p;
	},
	function reduceRemove(p,v) {
		p[v.Tag] = (p[v.Tag] || 0) - 1;
		p.total -= 1;
		return p;
	},
	function reduceInit() { return { total: 0 } }
);

var minDate = dateDim.bottom(1)[0].Date;
var maxDate = dateDim.top(1)[0].Date;

var fruitColors = d3
	.scaleOrdinal()
	.range(["#00CC00","#FFFF33","#CC0000","#CC00CC"])
	.domain(["apple","banana","cherry","dragonfruit"]);

/* Create charts */

var articlesByDay  = dc.lineChart("#chart-articlesperday");
articlesByDay
	.width(500).height(200)
	.dimension(dateDim)
	.group(dateGrp)
	.x(d3.scaleTime().domain([minDate,maxDate]));

var tagsPie = dc.pieChart("#chart-article-tags");
tagsPie
    .width(150).height(150)
    .dimension(tagsDim)
    .group(tagsGrp)
	.colors(fruitColors)
	.ordering(function (d) { return d.key });

var reviewerOrdering = authorGrp
	.all()
//	.sort(function (a, b) { return a.value.total - b.value.total })
	.map(function (d) { return d.key });

var tagsByAuthor = dc.barChart("#chart-tags-by-reviewer");
tagsByAuthor
	.width(600).height(400)
	.x(d3.scaleBand().domain(reviewerOrdering))
	.xUnits(dc.units.ordinal)
	.dimension(authorDim)
	.colors(fruitColors)
	.elasticY(true)
	.title(function (d) { return d.key + ": " + this.layer + ": " + d.value[this.layer] });

function sel_stack(i) {
  return function(d) {
	  return d.value[i];
  };
}

var tags = tagsGrp
	.all()
	.sort(function(a,b) { return b.value - a.value})
	.map(function (d) { return d.key });
tagsByAuthor.group(authorGrp, tags[0]);
tagsByAuthor.valueAccessor(sel_stack(tags[0]));
tags.shift(); // drop the first, as already added as .group()
tags.forEach(function (tag) {
	tagsByAuthor.stack(authorGrp, tag, sel_stack(tag));
});

dc.renderAll();
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.4.7/crossfilter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.1/dc.min.js"></script>
<div id="chart-articlesperday"></div>
<div id="chart-article-tags"></div>
<div id="chart-tags-by-reviewer"></div>

如您所见,Alice 发表了三篇文章,每篇文章分别标记有“苹果”、“香蕉”和“樱桃”,她的堆积条形图显示了这一点。

Full dashboard with line chart, pie chart and stacked bar chart working correctly

但是,每当单击条形图上她的列时,饼图就会显示她有 1 个“苹果”和 2 个“樱桃”。

enter image description here

我花了很长时间才达到这一点,所以可能有一些关于交叉过滤器分组的基本知识我还没有了解,所以非常欢迎任何见解、提示或评论。

最佳答案

确实,这是非常奇怪的行为,除了我以前遇到过几次之外,我不知道该怎么想。

如果你看documentation for group.all() ,它警告:

This method is faster than top(Infinity) because the entire group array is returned as-is rather than selecting into a new array and sorting. Do not modify the returned array!

我想否则它可能会在聚合时开始修改错误的垃圾箱。 (只是猜测,我还没有跟踪代码。)

你有:

var tags = tagsGrp
    .all()
    .sort(function(a,b) { return b.value - a.value})
    .map(function (d) { return d.key });

添加.slice(),复制数组,修复它:

var tags = tagsGrp
    .all().slice()
    .sort(function(a,b) { return b.value - a.value})
    .map(function (d) { return d.key });

correct filtering working fork of your fiddle

我们实际上有an open bug图书馆自己做这件事。啊! (很容易修复,但生成测试用例需要一些工作。)

关于dc.js - 为什么我的饼图在使用 dc.js 和 crossfilter.js 中的堆叠条形图进行过滤时显示不正确的组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57477975/

相关文章:

javascript - 我可以使用哪些工具来构建钻取图?

javascript - 使用文本框进行交叉过滤

javascript - dc lineChart 单击时弹出数据点信息

javascript - 两列上的单个交叉过滤器维度和组?

javascript - Dc.js 刷机滞后。与 dc.js 版本 1.3 不同,过滤多次

javascript - 我可以让 elasticX()、elasticY() 仅适用于上限、dc.js 吗?

javascript - 如何在 dc.js 上创建一个具有多个维度的组

javascript - 将数据从 dc.js dataTable 导出到 CSV

javascript - 如何在 crossfilter 中舍入 reduceSum 的值?

javascript - 如何从数组数组创建 "flattened"组?