堆叠条形图的弹性 X 轴,删除空箱 [dc.js]
Elastic X axis for stacked barchart, removing the empty bins [dc.js]
有这个 example that shows how you can make an elastic X axis that removes the empty bins using a fake group 和 chart.elasticX(true) 方法。
我正在尝试使用堆叠条形图来完成这项工作,但我遇到了问题。我稍微修改了上面示例的代码,为条形图使用堆叠组。 (我在数据中添加了一个 Earned 列,为其创建了一个假组并将其分配给 chart.stack 方法)。但对于某些 "Earned" 值,存在 d3.js 错误:
未捕获类型错误:无法读取未定义的 属性“1”。
#
更新:
此问题与此 which states that "The stack method expects your data to be equally length-ed". It is also related with this 有关,该 which states that "The stack method expects your data to be equally length-ed". It is also related with this 建议创建一个组合组来解决此问题。
#
这里是修改后的示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<title>dc.js - Filtering Example</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0/dc.min.css"/>
</head>
<body>
<div class="container">
<script type="text/javascript" src="header.js"></script>
<p>Example demonstrating using a "<a href="https://github.com/dc-js/dc.js/wiki/FAQ#fake-groups">Fake Group</a>" to remove
the empty bars of an ordinal bar chart when their values drop to zero.</p>
<p>(Note the use of <code><a href="https://github.com/dc-js/dc.js/blob/develop/web/docs/api-latest.md#dc.coordinateGridMixin+elasticX">.elasticX(true)</a></code>
to force calculation of the X domain each round.)</p>
<div id="chart-ring-year"></div>
<div id="chart-hist-spend"></div>
<div id="chart-row-spenders"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0/dc.min.js"></script>
<script type="text/javascript">
var yearRingChart = dc.pieChart("#chart-ring-year"),
spendHistChart = dc.barChart("#chart-hist-spend"),
spenderRowChart = dc.rowChart("#chart-row-spenders");
// use static or load via d3.csv("spendData.csv", function(error, spendData) {/* do stuff */});
var spendData = [
{Name: 'Mr A', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr C', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr A', Spent: '', Earned: '0', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2013},
{Name: 'Mr C', Spent: '', Earned: '', Year: 2013}
];
// normalize/parse data
spendData.forEach(function(d) {
d.Spent = d.Spent.match(/\d+/);
d.Earned = d.Earned.match(/\d+/);
});
function remove_empty_bins(source_group) {
return {
all:function () {
return source_group.all().filter(function(d) {
return d.value != 0;
});
}
};
}
// set crossfilter
var ndx = crossfilter(spendData),
yearDim = ndx.dimension(function(d) {return +d.Year;}),
spendDim = ndx.dimension(function(d) {return Math.floor(d.Spent/10);}),
earnDim = ndx.dimension(function(d) {return Math.floor(d.Earned/10);}),
nameDim = ndx.dimension(function(d) {return d.Name;}),
spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
spendPerName = nameDim.group().reduceSum(function(d) {return +d.Spent;}),
spendHist = spendDim.group().reduceCount(),
earnHist = earnDim.group().reduceCount(),
nonEmptyHist = remove_empty_bins(spendHist)
nonEmptyEarnHist = remove_empty_bins(earnHist)
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spendHistChart
.width(300).height(200)
.dimension(spendDim)
.group(nonEmptyHist)
.stack(nonEmptyEarnHist)
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticX(true)
.elasticY(true);
spendHistChart.xAxis().tickFormat(function(d) {return d*10}); // convert back to base unit
spendHistChart.yAxis().ticks(2);
spenderRowChart
.width(350).height(200)
.dimension(nameDim)
.group(spendPerName)
.elasticX(true);
dc.renderAll();
</script>
</div>
</body>
</html>
但是,如果您将挣值更改为
var spendData = [
{Name: 'Mr A', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr C', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr A', Spent: '', Earned: '0', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2013}, // This is the only change Earned from '' to ''
{Name: 'Mr C', Spent: '', Earned: '', Year: 2013}
]
然后它工作正常。
我遇到了同样的 d3 错误,所以我尝试用一个简单的例子重现它。
还有个相关问题
拜托,;这只是应用它的问题。
这确实是同一个问题,可以用组合组来解决。
combinedGroup = combine_groups(nonEmptyHist,nonEmptyEarnHist)
function sel_stack(i) {
return function(d) {
return d.value[i];
};
}
spendHistChart
.group(combinedGroup, 'spend', sel_stack(0))
.stack(combinedGroup, 'earn', sel_stack(1))
我不知道还有什么方法可以解决这个问题; d3.stack
需要相同大小的数组,dc.js 也会假定 key/value 数组相互对应。
有这个 example that shows how you can make an elastic X axis that removes the empty bins using a fake group 和 chart.elasticX(true) 方法。
我正在尝试使用堆叠条形图来完成这项工作,但我遇到了问题。我稍微修改了上面示例的代码,为条形图使用堆叠组。 (我在数据中添加了一个 Earned 列,为其创建了一个假组并将其分配给 chart.stack 方法)。但对于某些 "Earned" 值,存在 d3.js 错误:
未捕获类型错误:无法读取未定义的 属性“1”。
#
更新:
此问题与此
#
这里是修改后的示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<title>dc.js - Filtering Example</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0/dc.min.css"/>
</head>
<body>
<div class="container">
<script type="text/javascript" src="header.js"></script>
<p>Example demonstrating using a "<a href="https://github.com/dc-js/dc.js/wiki/FAQ#fake-groups">Fake Group</a>" to remove
the empty bars of an ordinal bar chart when their values drop to zero.</p>
<p>(Note the use of <code><a href="https://github.com/dc-js/dc.js/blob/develop/web/docs/api-latest.md#dc.coordinateGridMixin+elasticX">.elasticX(true)</a></code>
to force calculation of the X domain each round.)</p>
<div id="chart-ring-year"></div>
<div id="chart-hist-spend"></div>
<div id="chart-row-spenders"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0/dc.min.js"></script>
<script type="text/javascript">
var yearRingChart = dc.pieChart("#chart-ring-year"),
spendHistChart = dc.barChart("#chart-hist-spend"),
spenderRowChart = dc.rowChart("#chart-row-spenders");
// use static or load via d3.csv("spendData.csv", function(error, spendData) {/* do stuff */});
var spendData = [
{Name: 'Mr A', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr C', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr A', Spent: '', Earned: '0', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2013},
{Name: 'Mr C', Spent: '', Earned: '', Year: 2013}
];
// normalize/parse data
spendData.forEach(function(d) {
d.Spent = d.Spent.match(/\d+/);
d.Earned = d.Earned.match(/\d+/);
});
function remove_empty_bins(source_group) {
return {
all:function () {
return source_group.all().filter(function(d) {
return d.value != 0;
});
}
};
}
// set crossfilter
var ndx = crossfilter(spendData),
yearDim = ndx.dimension(function(d) {return +d.Year;}),
spendDim = ndx.dimension(function(d) {return Math.floor(d.Spent/10);}),
earnDim = ndx.dimension(function(d) {return Math.floor(d.Earned/10);}),
nameDim = ndx.dimension(function(d) {return d.Name;}),
spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
spendPerName = nameDim.group().reduceSum(function(d) {return +d.Spent;}),
spendHist = spendDim.group().reduceCount(),
earnHist = earnDim.group().reduceCount(),
nonEmptyHist = remove_empty_bins(spendHist)
nonEmptyEarnHist = remove_empty_bins(earnHist)
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spendHistChart
.width(300).height(200)
.dimension(spendDim)
.group(nonEmptyHist)
.stack(nonEmptyEarnHist)
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticX(true)
.elasticY(true);
spendHistChart.xAxis().tickFormat(function(d) {return d*10}); // convert back to base unit
spendHistChart.yAxis().ticks(2);
spenderRowChart
.width(350).height(200)
.dimension(nameDim)
.group(spendPerName)
.elasticX(true);
dc.renderAll();
</script>
</div>
</body>
</html>
但是,如果您将挣值更改为
var spendData = [
{Name: 'Mr A', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr C', Spent: '', Earned: '', Year: 2011},
{Name: 'Mr A', Spent: '', Earned: '0', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2012},
{Name: 'Mr B', Spent: '', Earned: '', Year: 2013}, // This is the only change Earned from '' to ''
{Name: 'Mr C', Spent: '', Earned: '', Year: 2013}
]
然后它工作正常。
我遇到了同样的 d3 错误,所以我尝试用一个简单的例子重现它。
还有
拜托,
这确实是同一个问题,可以用组合组来解决。
combinedGroup = combine_groups(nonEmptyHist,nonEmptyEarnHist)
function sel_stack(i) {
return function(d) {
return d.value[i];
};
}
spendHistChart
.group(combinedGroup, 'spend', sel_stack(0))
.stack(combinedGroup, 'earn', sel_stack(1))
我不知道还有什么方法可以解决这个问题; d3.stack
需要相同大小的数组,dc.js 也会假定 key/value 数组相互对应。