我现在已经有了几张不错的图表,但在这里我可能已经咬的比我能嚼的还多。我知道你通常不会考虑涉及负数分组的PieChart,但请耐心听我说。
我有一列值,我想在PieChart中显示。
PieChart应该有2个元素,1.正数的平均值2.负数的平均值。负数的平均值
饼片的文本元素应注意1.正平均值£? (?%)2. 负数平均值£? (?%)
我不能完全掌握的是PieChart如何处理负值。我的饼图没有负值元素的分片。所以想来想去,我能不能只在负数上加入一个-1的乘数。
我在想,把正数和负数分别提取到不同的数组中,用miltiplier调整负数数组,然后再把这两个数组重新纳入到我的饼图中,会不会提供一个合理的解决方案?如果不是太繁琐的话,我希望能在这里得到一些流程上的指导。
我只是期望,比如平均负值说20,平均正值60.而百分比显示为25%和75%。我感兴趣的是这两个数字之间的关系。
以上是我仅仅使用总值的情况。我还需要一些帮助,如何提取和使用平均值。
<div id="paybacksplit"></div>
<pre id="data">
Trade,Payback
1,85
2,74
3,-90
4,77
5,93
6,85
7,95
8,98
9,98
10,-88
11,10
12,98
13,93
14,65
15,76
16,81
17,0
18,0
19,96
20,-9
21,96
22,94
23,96
24,94
25,-88
26,8
27,85
28,88
29,90
</pre>
var pbschart = new dc.PieChart("#paybacksplit");
var trades = d3.csvParse(d3.select('pre#data').text());
trades.forEach(function(x) {
x.Payback = +x.Payback;
});
var ndx = crossfilter(trades),
tradeDimension = ndx.dimension(function(d) {
if (d.Payback >= 0)
return "Profitable";
else
return "Losing";
});
paybackSumGroup = tradeDimension.group().reduceSum(function(d) {return d.Payback;});
pbschart
.width(768)
.height(480)
.slicesCap(2)
.innerRadius(2)
.dimension(tradeDimension)
.group(paybackSumGroup)
.legend(dc.legend().highlightSelected(true))
.on('pretransition', function(chart) {
chart.selectAll('text.pie-slice').text(function(d) {
return d.data.key + ' £ '+ d.data.value + dc.utils.printSingleValue((d.endAngle - d.startAngle) / (2*Math.PI) * 100) + '%';
})
});
pbschart.render();
jsfiddle是 此处
接下来发生了什么。
Gordons的答复帮了大忙,但我还没有熟练到足以弄清下一阶段的工作,即返回平均值。
然而,由于数据来自于我自己的数据,我只是重组了输出,为每个项目提供一列ProfitLoss,第二列提供数值(负值转换为正值)。
以我有限的dc.js知识,重新调整我的数据库输出是比较容易的,我最后得到的是
<div id="paybacksplit2"></div>
<!-- here's a way to load data from a jsfiddle, to avoid CORS
problems - see http://stackoverflow.com/a/22896088/676195
-->
<pre id="data">
Trade,Payback
Prof,85
Prof,74
Loss,90
Prof,77
Prof,93
Prof,85
Prof,95
Prof,98
Prof,98
Loss,88
Prof,10
Prof,98
Prof,93
Prof,65
Prof,76
Prof,81
Prof,0
Prof,0
Prof,96
Loss,9
Prof,96
Prof,94
Prof,96
Prof,94
Loss,88
Prof,8
Prof,85
Prof,88
Prof,90
</pre>
和
var pbschart2 = new dc.PieChart("#paybacksplit2");
var numberFormat = d3.format("(.2f");
var trades = d3.csvParse(d3.select('pre#data').text());
trades.forEach(function(x) {
x.payback = +x.Payback
x.trade = x.Trade
;
});
var ndx = crossfilter(trades),
tradeDimension = ndx.dimension(function(d) {return d.trade;});
paybackSumGroup = tradeDimension.group().reduceSum(function(d) {return d.payback;});
var nameDim = ndx.dimension(function(d) { return d.trade; })
var totalValGroup = nameDim.group().reduce(reduceAddVal, reduceRemoveVal, reduceInitialVal);
var result = totalValGroup.top(Infinity);
console.log(result);
function reduceAddVal(p, v) {
++p.count;
p.totalVal += v.payback;
p.average = p.totalVal / p.count;
return p;
}
function reduceRemoveVal(p, v) {
--p.count;
p.totalVal -= v.payback;
p.average = p.totalVal / p.count;
return p;
}
function reduceInitialVal() {
return {
count: 0,
totalVal: 0,
average: 0
};
}
pbschart2
.width(768)
.height(200)
.slicesCap(2)
.dimension(nameDim)
.group(totalValGroup)
.valueAccessor(function (p) {
return p.value.average;
})
.legend(dc.legend().highlightSelected(true))
.on('pretransition', function(chart) {
chart.selectAll('text.pie-slice').text(function(d) {
return ' £ '+ numberFormat(d.data.value.average);
})
});
pbschart2.render();
这给了我以下的结果。
这差不多就是我想要的东西。
更新的小提琴 此处
也许以后我可以在dc.js中做更多的事情,但由于我可以选择定义自己的数据提取,这对我来说是目前最简单的选择。
谢谢Gordon,我正在一点一点的进步。
在dc.js中,有很多不同的 "accessors",它们允许你提供一个函数,它可以
在这种情况下 valueAccessor 是有帮助的。
pbschart
.valueAccessor(kv => Math.abs(kv.value))