如何在 dc.js 中呈现 timeseries/categorical 堆积条形图,过滤堆栈和条形图
How to render timeseries/categorical stacked bar chart in dc.js, filtering stack and bar
我发现的大多数示例都使用具有时间和数字的数据
var data = [
{
"Time": "19-Jan-2018 11:24:49.000 UTC",
"Speed": 1.885
},
{
"Time": "19-Jan-2018 11:24:59.000 UTC",
"Speed": 1.875
},
{
"Time": "19-Jan-2018 11:25:00.000 UTC",
"Speed": 1.878
},
{
"Time": "19-Jan-2018 11:25:01.000 UTC",
"Speed": 1.876
}
]
我正在寻找堆栈类型
var data = [
{
"Time": "19-Jan-2018 11:24:49.000 UTC",
"type": "CAT"
},
{
"Time": "19-Jan-2018 11:24:59.000 UTC",
"type": "DOG"
},
{
"Time": "19-Jan-2018 11:25:00.000 UTC",
"type": "CAT"
},
{
"Time": "19-Jan-2018 11:25:01.000 UTC",
"Type": "BAT"
}
]
如何堆叠分类数据,同时允许用户 select time/category 对,如下面的 Example?
我将示例改编为 time/category this fiddle 中的数据。
这些日期只会在 Chrome 中解析,所以
const parseDate = d3.utcParse("%d-%b-%Y %H:%M:%S.%L UTC");
data.forEach(d => {
d.Time = parseDate(d.Time);
})
我将按键功能更改为使用 ,
function multikey(x,y) {
return x + ',' + y;
}
function splitkey(k) {
return k.split(',');
}
我还更改了假组 stack_second
以将字符串日期从多键转换回日期,并将类别初始化为 0(因为每个 X 都必须存在每个堆栈)。
function stack_second(group, categories) {
return {
all: function() {
var all = group.all(),
m = {};
// build matrix from multikey/value pairs
all.forEach(function(kv) {
var ks = splitkey(kv.key);
m[ks[0]] = m[ks[0]] || Object.fromEntries(categories.map(c=>[c,0]));
m[ks[0]][ks[1]] = kv.value;
});
// then produce multivalue key/value pairs
return Object.keys(m).map(function(k) {
return {key: new Date(k), value: m[k]};
});
}
};
}
从源数据中获取类别数组:
const categories = Array.from(new Set(data.map(d => d.Type)).values());
处理date/time时,您必须选择适合您数据的d3 time interval。在这里分钟看起来是正确的。到处使用 UTC d3-time 方法,因为您的源数据是 UTC。
const interval = d3.utcMinute;
计算xscale域并应用:
let extent = d3.extent(data, d=>d.Time);
extent[1] = interval.offset(extent[1], 1)
chart
.x(d3.scaleTime().domain(extent))
.xUnits(interval.range)
正确的报价数量,也采用 UTC 格式:
chart.xAxis().ticks(d3.utcMinute).tickFormat(d3.utcFormat('%H:%M'))
将堆叠和楔形之间的颜色匹配
.colors(d3.scaleOrdinal().domain(categories).range(d3.schemeCategory10))
Crossfilter初始化,使用区间和类别:
const interval = d3.utcMinute; // choose appropriate to your data
var cf = crossfilter(data),
timeTypeDim = cf.dimension(function(d) { return multikey(interval(d.Time), d.Type); }),
timeTypeGroup = timeTypeDim.group(), // reduceCount by default
stackedGroup = stack_second(timeTypeGroup, categories);
这里是完整的图表代码,尽管我们已经讨论了相关部分:
function sel_stack(i) {
return function(d) {
return d.value[i];
};
}
chart
.width(600)
.height(400)
.colors(d3.scaleOrdinal().domain(categories).range(d3.schemeCategory10))
.controlsUseVisibility(true)
.x(d3.scaleTime().domain(extent))
.xUnits(interval.range)
.margins({left: 80, top: 20, right: 10, bottom: 20})
.brushOn(false)
.clipPadding(10)
.title(function(d) {
return d.key + '[' + this.layer + ']: ' + d.value[this.layer];
})
.legend(dc.legend().x(540).y(50))
.dimension(timeTypeDim)
.group(stackedGroup, categories[0], sel_stack(categories[0]))
.renderLabel(true);
我发现的大多数示例都使用具有时间和数字的数据
var data = [
{
"Time": "19-Jan-2018 11:24:49.000 UTC",
"Speed": 1.885
},
{
"Time": "19-Jan-2018 11:24:59.000 UTC",
"Speed": 1.875
},
{
"Time": "19-Jan-2018 11:25:00.000 UTC",
"Speed": 1.878
},
{
"Time": "19-Jan-2018 11:25:01.000 UTC",
"Speed": 1.876
}
]
我正在寻找堆栈类型
var data = [
{
"Time": "19-Jan-2018 11:24:49.000 UTC",
"type": "CAT"
},
{
"Time": "19-Jan-2018 11:24:59.000 UTC",
"type": "DOG"
},
{
"Time": "19-Jan-2018 11:25:00.000 UTC",
"type": "CAT"
},
{
"Time": "19-Jan-2018 11:25:01.000 UTC",
"Type": "BAT"
}
]
如何堆叠分类数据,同时允许用户 select time/category 对,如下面的 Example?
我将示例改编为 time/category this fiddle 中的数据。
这些日期只会在 Chrome 中解析,所以
const parseDate = d3.utcParse("%d-%b-%Y %H:%M:%S.%L UTC");
data.forEach(d => {
d.Time = parseDate(d.Time);
})
我将按键功能更改为使用 ,
function multikey(x,y) {
return x + ',' + y;
}
function splitkey(k) {
return k.split(',');
}
我还更改了假组 stack_second
以将字符串日期从多键转换回日期,并将类别初始化为 0(因为每个 X 都必须存在每个堆栈)。
function stack_second(group, categories) {
return {
all: function() {
var all = group.all(),
m = {};
// build matrix from multikey/value pairs
all.forEach(function(kv) {
var ks = splitkey(kv.key);
m[ks[0]] = m[ks[0]] || Object.fromEntries(categories.map(c=>[c,0]));
m[ks[0]][ks[1]] = kv.value;
});
// then produce multivalue key/value pairs
return Object.keys(m).map(function(k) {
return {key: new Date(k), value: m[k]};
});
}
};
}
从源数据中获取类别数组:
const categories = Array.from(new Set(data.map(d => d.Type)).values());
处理date/time时,您必须选择适合您数据的d3 time interval。在这里分钟看起来是正确的。到处使用 UTC d3-time 方法,因为您的源数据是 UTC。
const interval = d3.utcMinute;
计算xscale域并应用:
let extent = d3.extent(data, d=>d.Time);
extent[1] = interval.offset(extent[1], 1)
chart
.x(d3.scaleTime().domain(extent))
.xUnits(interval.range)
正确的报价数量,也采用 UTC 格式:
chart.xAxis().ticks(d3.utcMinute).tickFormat(d3.utcFormat('%H:%M'))
将堆叠和楔形之间的颜色匹配
.colors(d3.scaleOrdinal().domain(categories).range(d3.schemeCategory10))
Crossfilter初始化,使用区间和类别:
const interval = d3.utcMinute; // choose appropriate to your data
var cf = crossfilter(data),
timeTypeDim = cf.dimension(function(d) { return multikey(interval(d.Time), d.Type); }),
timeTypeGroup = timeTypeDim.group(), // reduceCount by default
stackedGroup = stack_second(timeTypeGroup, categories);
这里是完整的图表代码,尽管我们已经讨论了相关部分:
function sel_stack(i) {
return function(d) {
return d.value[i];
};
}
chart
.width(600)
.height(400)
.colors(d3.scaleOrdinal().domain(categories).range(d3.schemeCategory10))
.controlsUseVisibility(true)
.x(d3.scaleTime().domain(extent))
.xUnits(interval.range)
.margins({left: 80, top: 20, right: 10, bottom: 20})
.brushOn(false)
.clipPadding(10)
.title(function(d) {
return d.key + '[' + this.layer + ']: ' + d.value[this.layer];
})
.legend(dc.legend().x(540).y(50))
.dimension(timeTypeDim)
.group(stackedGroup, categories[0], sel_stack(categories[0]))
.renderLabel(true);