I have a Composite Linechart
The .elasticX(true) does not work :/ Could Someone help me
var composite = dc.compositeChart("#durationline-chart");
composite.width(1500).height(350)
.group(Durations)
.brushOn(true)
.yAxisLabel("Duration")
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.margins({ top: 10, left: 50, right: 10, bottom: 50 })
.elasticY(true)
.elasticX(true)
.renderlet(function(chart) {
chart.selectAll("g.x text")
.attr('transform', "rotate(+20)");
})
.compose([
dc.lineChart(composite)
.group(Testcase_Time, "Time")
.colors('#1E90FF'),
dc.lineChart(composite)
.group(Testcase_Smartkey, "Smartkey")
.colors('red')]);
EDIT: Here is the jsfiddle: https://jsfiddle.net/gordonwoodhull/o9xx3fmm/
I think you mean the elastic is not kicking in when the chart is filtered.
This is because crossfilter still returns bins if they are empty - they just have value zero. So dc.js still detects the domain of all the bins, including the empty ones.
What you can do is use a fake group to remove the empty bins
function remove_empty_bins(source_group) {
return {
all:function () {
return source_group.all().filter(function(d) {
return d.value != 0;
});
}
};
}
var filtered_group = remove_empty_bins(group);
chart.dimension(dim)
.group(filtered_group)
...
Then dc.js will detect only the domain of non zero values. More details in the FAQ.
You have to apply this to all groups that make up the chart.
Related
I have a problem with a scatter chart in dc.js using crossfilter.js. Actually my problem is double. When I use the function:
function remove_empty_bins(source_group) {
return {
all: function () {
return source_group.all().filter(function(d) {
//return Math.abs(d.value) > 0.00001; // if using floating-point numbers
return d.value !== 0; // if integers only
});
}
};
};
The elasticX(true) and elasticY(true) work but the "unfiltered" data still display on my scatterChart. When i use the same function with return true; instead of return d.value !== 0; the "unfiltered" data disappear but neither elasticX nor elasticY work...
Any idea to fix it ?
Moreover, my bubbleChart does not react to this changement. The x-Axis doesn't uses the elasticX parameter... The range always stays with the global Minimum and Maximum of all the datas...
Thanks a lot !!
My scatterChart:
var dim1 = ndx1.dimension(function (d) {return [+d.OperatingCluster,+d.FreqErrorCluster] ;});
var group1 = dim1.group();
clusterOutsidescatterPlot
//.width(300)
.height(rowHeight)
.x(d3.scaleLinear().domain([0, 2000]))
.y(d3.scaleLinear().domain([0, 100]))
.yAxisLabel("Nombre d'occurences de l'erreur")
.xAxisLabel("Apparition dans le cluster (secondes)")
.yAxisPadding('5%')
.xAxisPadding('5%')
.transitionDuration(0)
// .clipPadding(100)
.dimension(dim1)
.group(remove_empty_bins(group1))
.elasticX(true)
.elasticY(true)
.brushOn(false)
.excludedOpacity(0.5)
.on("postRender", function(chart){
chart.select("svg")
.attr("viewBox", rowViewBoxAttr)
.attr("preserveAspectRatio", "xMinYMin")
.attr("width", "100%")
.attr("height", "100%");
chart.redraw();
});
I am not being able to have the percentage display over the bar chart with the code:
chart3barchart2
.width(500)
.height(500)
.x(d3.scale.ordinal().domain(['18-21', '22-26', '27-30', '31-35']))
.xUnits(dc.units.ordinal)
.margins({top: 24, left: 0, right: 10, bottom: 20})
.colors(d3.scale.category10())
.brushOn(false)
.ordinalColors(['#FC6E4C'])
.dimension(ageDim)
.group(ageGroup)
.valueAccessor(function (d) { return parseInt((d.value.RespondCount/ntotal2.all()[0].value.RespondCount* 100).toFixed(0),10) + "%";})
.elasticY(true)
.yAxisPadding('60%')
.renderLabel(true)
.barPadding(0.2)
.outerPadding(0.6);
dc.renderAll("viz2");
See this fiddle for the whole code.
each time I put the "%" to .valueAccessor(function (d) { return parseInt((d.value.RespondCount/ntotal2.all()[0].value.RespondCount* 100).toFixed(0),10) + "%";}) the graph disappear altogether without showing an error in the browser console. Does someone has an idea ? thank you!
Fiddle for Reference: https://jsfiddle.net/33228p1d/4/
Referencing Cost Average chart on the page. Chart rendered with the following code:
var cpa = ndx.dimension(function (d) {
return d.location;
});
var cpaGroup = cpa.group().reduceSum(function (d) {
return d.total;
});
And the chart itself: (styling left off for brevity)
cpaChart
.dimension(cpa)
.group(cpaGroup)
.label(function (d) {
return d.key + " $" + d.value;
})
.title(function (d) {
return d.value;
})
.elasticX(true)
.ordering(function (d) { return -d.value })
.xAxis().ticks(4);
Right now, it is showing the total for Front and Back locations accurately.
What I want it to do is show total divided by number of unique PO's for that location to show the average cost per location.
So, for example, for Back I have two unique purchase orders totaling $396. What I would like to see is 396 / 2 for an average cost per location of 198.
If you're still willing to use Reductio, track sum and exceptionCount on the same group and then divide them in the valueAccessor accessor:
var cpaGroup = reductio()
.sum('total')
.exception(function(d) { return d.po; })
.exceptionCount(true)(cpa.group());
cpaChart
.width(400)
.height(200)
.margins({ top: 20, left: 10, right: 10, bottom: 20 })
.dimension(cpa)
.group(cpaGroup)
.ordinalColors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb'])
.label(function (d) {
return d.key + " $" + (Math.round(d.value.sum / d.value.exceptionCount));
})
.title(function (d) {
return d.value;
})
.valueAccessor(function(d) {
return d.value.sum / d.value.exceptionCount;
})
.elasticX(true)
.ordering(function (d) { return -d.value })
.xAxis().ticks(4);
Example: https://jsfiddle.net/7wbcref9/
I have the following composite chart made in dc.js:
barChart
.dimension(savingsDimension)
.colors('#009900')
.centerBar(true)
.elasticY(true)
.title(function(d) { return d.key + ": " + d.value; });
barChart2
.dimension(savingsDimension)
.colors('#000099')
.centerBar(true)
.elasticY(true)
.title(function(d) { return d.key + ": " + d.value; });
var lineChart = dc.lineChart(compositeChart)
.dimension(savingsDimension)
.colors('red')
.useRightYAxis(true)
.renderDataPoints({
radius: 3,
fillOpacity: 0.5,
strokeOpacity: 0.8
});
var xUnits = data.map(function (d) {return d.short_date; }).sort();
compositeChart
.width(1300)
.height(350)
.x(d3.scale.ordinal().domain(xUnits))
.xUnits(dc.units.ordinal)
.xAxisLabel('Month')
.brushOn(false)
.elasticY(true)
.margins({left: 80, top: 10, right: 190, bottom: 80})
.legend(dc.legend().x(1160).y(220).itemHeight(13).gap(5))
.compose([barChart, barChart2,
lineChart
]).renderlet(function(chart){
chart.selectAll("g.x text")
.attr('transform', "rotate(-65)")
.attr('x', -20);
});
barChart.group(fSavingsDimensionGroup, ' First Savings');
barChart2.group(sSavingsDimensionGroup, 'Second Savings');
The first thing I am having trouble with is making it so that I can select an x-range on this composite chart which will then filter all of my other charts. Right now, I can select certain bars and filter it that way, but I can't select a range like in this example: http://dc-js.github.io/dc.js/examples/filtering.html
I tried using .controlsUseVisibility(true) but it just errors out.
Also, even though I have .centerBar(true) on both my bar charts, the labels still aren't centered. Not sure what I am doing wrong there.
Edit #1:
Changed the code to:
compositeChart
.width(1300)
.height(350)
.x(d3.time.scale().domain([savingsDimension.bottom(1)
[0].billing_period_start, savingsDimension.top(1)
[0].billing_period_start]))
[0].billing_period_start, savingsDimension.top(1)
[0].billing_period_start))
.xAxisLabel('Month')
.elasticY(true)
.margins({left: 80, top: 10, right: 190, bottom: 80})
.legend(dc.legend().x(1160).y(220).itemHeight(13).gap(5))
.renderlet(function(chart){
chart.selectAll("g.x text")
.attr('transform', "rotate(-65)")
.attr('x', -36)
.attr('y', -20);
});
compositeChart.xAxis().tickFormat(d3.time.format('%m-%Y')).ticks(24);
compositeChart.xUnits(d3.time.months)
And the chart now looks like:
The bars are weirdly spaced out and I have no idea why.
I can now select a range on the chart, but it doesn't actually do any sort of filtering to the chart or any other chart on the page.
Currently the filtering behavior is selected by the type of x scale, so to get continuous brushing you could use a quantitative scale such as d3.time.scale(), convert your dates to date objects, and then use xAxis().tickFormat() to display them the way you want.
Here is the feature request to allow the range brush on ordinal charts. It is mainly a question of how to design the feature in a general way.
You are moving the tick labels with your renderlet, so you should adjust the displacement there in order to center your labels.
This is a piece of a code in which I am able to get data correctly.But the issue is i am not able to plot chart.
Please refer this link to find chart image which I am getting
// This is where the composite chart code is starting.
CompositeChart: function (chartConfig, chartManager, meta) {
var data = meta.data;
var panelDetails = this.panelDetails(chartConfig.chartName);
var chart = dc.compositeChart(panelDetails.id);
var yAxisGroup = [];
if (chartConfig.xDomainType == "Date" && !(data[0][meta.header[chartConfig.x]] instanceof Date)) {
var dateFormater = d3.time.format("%Y-%m-%d");
data.forEach(function (d, i) {
d[meta.header[chartConfig.x]] = dateFormater.parse(d[meta.header[chartConfig.x]]);
});
}
var xAxis = chartManager.cf.dimension(function (d) {
var val = d[meta.header[chartConfig.x]];
var result = (chartManager.dimValues[chartConfig.x]) ? chartManager.dimValues[chartConfig.x][val] : val;
return result;
});
yAxisGroup = (chartConfig.y);
var temp = yAxisGroup[0];
var temp1 = yAxisGroup[1];
var yDim1 = xAxis.group().reduceSum(function (d) {
var val = d[meta.header[temp]];
var result = (chartManager.dimValues[temp]) ? chartManager.dimValues[temp][val] : val;
return result;
});
var yDim2 = xAxis.group().reduceSum(function (d) {
var val = d[meta.header[temp1]];
var result = (chartManager.dimValues[temp1]) ? chartManager.dimValues[temp1][val] : val;
return result;
});
chart
.width(panelDetails.width)
.height(panelDetails.height)
.margins({
top: 35,
right: 55,
bottom: 30,
left: 45
})
.renderHorizontalGridLines(true)
.shareColors(true)
.compose([
dc.lineChart(chart)
.dimension(xAxis)
.dashStyle([2, 2])
.group(yDim1),
dc.lineChart(chart)
.dimension(xAxis)
.dashStyle([5, 5])
.group(yDim2)
])
.brushOn(false);
this.addXDomain(chartConfig, meta, chart, xAxis);
chart.render();
this.chartStore[chartConfig.chartName] = chart;
},
When I debug the data is fine. I am able to print it on console.But no luck on Chart
I am sharing data of X-Axis while grouping Y-Axis data. Any Solutions?
Note: Console is showing no error or exception.
Can any body help me find the parent chart? Guess that is the problem but I am not sure I need to pass the parent chat in compose function.
Fiddle Link
It's hard to know for sure, but you might try putting your xaxis on the composite chart rather than each composed chart.
Here is a working chart that I've built:
var actuals = dc.barChart(compositeChart)
.gap(65)
.group(group)
.valueAccessor(function (d) {
return d.value.Actual;
});
var budgets = dc.barChart(compositeChart)
.gap(65)
.group(group)
.valueAccessor(function (d) {
return d.value.Budget;
});
compositeChart
.width(1000)
.height(300)
.margins({top: 20, right: 45, bottom: 40, left: 50})
.dimension(monthDimension)
.group(group)
.elasticY(true)
.x(d3.time.scale().domain(timeExtent))
.xUnits(d3.time.months)
.round(d3.time.month.round)
.renderHorizontalGridLines(true)
.compose([budgets, actuals])
.brushOn(true)
.title(function (d) {
return [
"Engagement: " + d.value.engagement,
"Amount:" + d.value.amount
].join("\n");
})
.renderlet(function (chart) {
chart.selectAll("g._1").attr("transform", "translate(" + 20 + ", 0)");
chart.selectAll("g._0").attr("transform", "translate(" + 1 + ", 0)");
});
Note that the budget and actual charts do not define an x or xUnits method. This is left to the composite chart. Not sure that whether this is required or not, but I imagine you need to define x for the composite chart.