Reputation: 1116
I've created a linechart showing averages using Dimensional Charting javascript library dc.js. I'm displaying a rowchart, linechart, and barchart.
When I select one category then year wise average line chart and month wise average line chart display. But when I select one particular year and one category the time month wise average line chart does not display.
skuRowChart = dc.rowChart("#chart-row-spenders");
yearPieChart = dc.pieChart("#chart-pie-year");
yearLineChart = dc.lineChart('#Yearly-move-chart');
spendHistChart22 = dc.barChart("#chart-hist-spend22");
moveChart1 = dc.lineChart('#monthly-move-chart1');
function reduceAdd(p, v) {
++p.count;
p.total += v.sr;
p.average = p.total / p.count
return p;
}
function reduceRemove(p, v) {
--p.count;
p.total -= v.sr;
p.average = p.total / p.count
return p;
}
function reduceInitial() {
return {count: 0, total: 0, average: 0};
}
var parseDate = d3.time.format("%m/%d/%Y").parse;
var yearFormat = d3.time.format('%Y');
var monthFormat = d3.time.format("%m");
//var monthNameFormat = d3.time.format("%b");
var monthNameFormat = d3.time.format('%m.%b');
var
spendData = [
{ct:'KF', kw:'Amazon', sr: '35978',sd:'12/29/2016'},
{ct:'KF', kw:'Amazon', sr: '32178',sd:'11/2/2016'},
{ct:'KF', kw:'Amazon', sr: '30978',sd:'1/2/2017'},
{ct:'KF', kw:'Amazon', sr: '28978',sd:'1/15/2017'},
{ct:'KF',kw:'Build',sr:'28343',sd:'12/29/2016'},
{ct:'KF',kw:'Build',sr:'29653',sd:'11/29/2016'},
{ct:'KF',kw:'Build',sr:'26343',sd:'10/29/2016'},
{ct:'KF',kw:'Build',sr:'28343',sd:'2/2/2017'},
{ct:'KF',kw:'Build',sr:'28343',sd:'3/26/2017'},
{ct:'KF',kw:'Homedepot',sr:'221206',sd:'12/29/2016'},
{ct:'KF',kw:'Homedepot',sr:'203206',sd:'11/27/2016'},
{ct:'KF',kw:'Homedepot',sr:'193206',sd:'10/2/2016'},
{ct:'KF',kw:'wayfair',sr:'77794',sd:'12/29/2016'},
{ct:'KF',kw:'wayfair',sr:'71794',sd:'11/9/2016'},
{ct:'KF',kw:'wayfair',sr:'70794',sd:'1/9/2017'},
{ct:'KF',kw:'wayfair',sr:'74794',sd:'2/19/2017'},
{ct:'KF',kw:'wayfair',sr:'74794',sd:'3/21/2017'},
{ct:'KF',kw:'Houzz',sr:'408684',sd:'12/29/2016'},
{ct:'KF',kw:'Houzz',sr:'42684',sd:'11/22/2016'},
{ct:'KF',kw:'Houzz',sr:'46684',sd:'10/2/2016'},
{ct:'KF',kw:'Houzz',sr:'496684',sd:'1/2/2017'},
{ct:'KF',kw:'Houzz',sr:'49684',sd:'2/2/2017'},
{ct:'KF',kw:'Houzz',sr:'49664',sd:'3/2/2017'},
{ct:'KF',kw:'express',sr:'32004',sd:'12/29/2016'},
{ct:'KF',kw:'express',sr:'30004',sd:'11/2/2016'},
{ct:'KF',kw:'express',sr:'35004',sd:'10/2/2016'},
{ct:'KF',kw:'express',sr:'35004',sd:'12/2/2016'},
{ct:'KF',kw:'yahoo',sr:'115618',sd:'12/29/2016'},
{ct:'KF',kw:'yahoo',sr:'12546',sd:'10/2/2016'},
{ct:'KF',kw:'yahoo',sr:'65423',sd:'11/29/2016'},
{ct:'KF',kw:'yahoo',sr:'25698',sd:'10/29/2016'},
{ct:'KF',kw:'google',sr:'404991',sd:'1/29/2017'},
{ct:'KF',kw:'google',sr:'404991',sd:'2/2/2017'},
{ct:'KF',kw:'google',sr:'404991',sd:'3/12/2017'},
{ct:'KF',kw:'google',sr:'404991',sd:'3/3/2017'},
{ct:'KF',kw:'pingserach',sr:'273944',sd:'12/29/2016'}
];
// d3.csv("hhh.csv", function (error, salesrank) {
spendData.forEach(function (d) {
d.sr = +d.sr;
d.Date = parseDate(d.sd);
d.Year = yearFormat(d.Date);
d.Month = monthNameFormat(d.Date);
});
var ndx = crossfilter(spendData);
var all = ndx.groupAll();
SkuDim = ndx.dimension(function (d) {return d.kw; });
spendPerSku = SkuDim.group().reduceCount();
yearDim = ndx.dimension(function (d) {return d.Year; });
year_total = yearDim.group().reduceCount(function (d) {return d.sr;});
exptAvgGroup = yearDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);
monthDim = ndx.dimension(function (d) {return d.Month; });
exptAvgGroup11 = monthDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);
month_total = monthDim.group().reduceCount(function (d) { return d.sr;});
skuRowChart
.width(350)
.height(300)
.dimension(SkuDim)
.group(spendPerSku)
.elasticX(true)
.x(d3.scale.linear().domain([6, 20]))
.ordering(function (d) {
return -d.value
})
// .cap(40)
//.margins({top: -30, left: 0, right: 0, bottom: 0})
.controlsUseVisibility(true);
skuRowChart.data(function (group) {
return group.top(50);
});
yearPieChart
.width(250).height(250)
.dimension(yearDim)
.group(year_total)
.innerRadius(60)
.controlsUseVisibility(true);
yearLineChart
.width(380)
.height(280)
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.renderArea(true)
.valueAccessor(function (p) {
//console.log("p.value.average: ", p.value.average) //displays the avg fine
return d3.round(p.value.average, 0);
})
//.brushOn(true)
.elasticY(true)
.xAxisLabel('Years')
.yAxisLabel('Review Count')
//.dimension(moveMonths)
.dimension(yearDim)
.group(exptAvgGroup)
//.margins({ top: 10, left: 60, right:40, bottom: 60 })
.margins({top: 0, left: 60, right: 30, bottom: 60})
spendHistChart22
.width(400).height(280)
.dimension(monthDim)
//.dimension(dateeddim)
// .group(dateeddimGroup)
.group(month_total)
.xAxisLabel('Months')
.yAxisLabel('')
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.ordering(function(d) { return d.key })
.elasticX(true)
.elasticY(true)
.margins({ top: 10, left: 60, right: 40, bottom: 60 })
.controlsUseVisibility(true)
spendHistChart22.xAxis().tickFormat(d => d.substr(3))
moveChart1
.width(380)
.height(310)
//.x(d3.scale.ordinal().domain(map(function (d) {return d.Month;})))
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.valueAccessor(function (p) {
//console.log("p.value.average: ", p.value.average) //displays the avg fine
return d3.round(p.value.average, 0);
})
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.renderArea(true)
//.clipPadding(10)
//.brushOn(false)
.elasticY(true)
.xAxisLabel('Months')
.yAxisLabel('')
.dimension(monthDim)
.group(exptAvgGroup11)
.margins({top: 40, left: 60, right: 30, bottom: 60})
moveChart1.xAxis().tickFormat(d => d.substr(3))
dc.renderAll();
https://jsfiddle.net/pramod24/kk4j0bzn/4/
Upvotes: 0
Views: 113
Reputation: 20150
You have to watch out whenever you divide by something that is potentially zero.
dc.js won't sanitize your data very much, so when you see a blank chart, it's probably bad data.
Without trying to debug anything, I tried fixing the first thing that stood out to me, those divisions by p.count
that don't check if p.count
is zero.
You probably want your averages to drop to zero when the count is zero. (Technically I guess there should be gaps in the line, but I won't get into that unless you're interested.)
This seems to fix the problem:
function reduceAdd(p, v) {
++p.count;
p.total += v.sr;
p.average = p.count ? p.total / p.count : 0;
return p;
}
function reduceRemove(p, v) {
--p.count;
p.total -= v.sr;
p.average = p.count ? p.total / p.count : 0;
return p;
}
Fork of your fiddle: https://jsfiddle.net/gordonwoodhull/q4aquukz/1/
Would you be so kind as to point to the example where you got the bad code, so I can correct it or leave a comment?
Upvotes: 2