Bubbles are not showing in Bubble chart using dc.jc - dc.js

I am making a bubble chart using dc.js , crossfilter.js but bubbles are not showing in the chart !!!! It is just showing x axis and y axis but the bubbles are disappeared.
I was trying make this bubble chart in click to see
here is my code :
var dateDim = ndx.dimension(function(d) {return d.Date;});
var minDate = dateDim.bottom(1)[0].Date;
var maxDate = dateDim.top(1)[0].Date;
console.log(minDate);
console.log(maxDate);
//var ageDim = ndx.dimension(function(d){return +d.Age;});
var daySum = dateDim.group().reduceSum(function(d){return 1;});
//print_filter("ageSum");
// var hits = dateDim.group().reduceSum(function(d) {return d.Age;});
var brush = d3.svg.brush();
suicideBubbleChart
.width(990).height(200)
.transitionDuration(1500)
.dimension(dateDim)
.group(daySum)
.colors(d3.scale.category10())
.x(d3.time.scale().domain([minDate,maxDate]))
.y(d3.time.scale().domain([minDate,maxDate]))
.r(d3.scale.linear().domain([0, 4000]))
.minRadiusWithLabel(15)
.yAxisLabel("Suicides")
.elasticY(true)
.yAxisPadding(100)
.elasticX(true)
.xAxisPadding(200)
.maxBubbleRelativeSize(0.07)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.renderLabel(true)
.renderTitle(true);
Thank you.

I fixed enough to start getting stuff showing up on the chart.
There was a space before Date that caused that field name to come out wrong, and the date format was wrong, and I added a radiusValueAccessor.
var dateFormat = d3.time.format('%m/%d/%Y');
...
.r(d3.scale.linear().domain([0, 10]))
.radiusValueAccessor(function(d) {
return d.value;
})
http://jsfiddle.net/gordonwoodhull/wjeonreq/15/
Obviously it is still not the chart you want, but hopefully now that you have some stuff showing up on the screen, you can start to shape and debug it.
In particular, you will need a valueAccessor in order to place the bubbles in Y, and a Y scale.
It is one of the frustrating things about dc & d3 that if something doesn't work, then you just get an empty chart. The way I tracked this down, after dealing with the errors above, which showed up in the console, was
look at daySum.all() to make sure the data was okay (it was, after the date correction)
Inspect the svg element in the Elements tab of the Developer tools. The g.chart-body inside there has the actual content. I saw that the bubbles were there but had radius zero. Then I looked back at the stock example to see what radius setup must be missing.

Related

DC.JS/Crossfilter: Percentage on y-axis of a bar chart with linear x-axis?

I want to display percentages on the y-axis of a dc.js barchart that can dynamically change when filtering the chart itself or some other charts.
Here is my case:
var ndx = crossfilter(dataCsvInitial);
var all = ndx.groupAll();
var accCredLimDim = ndx.dimension(function(d) { return d.acct_curr_crlimit;});
Then, I group by bins:
var value_range_credlim = maxCredLim - minCredLim; // defined earlier...
var nb_of_bins_credlim = 50,
bin_width_credlim = value_range_credlim/nb_of_bins_credlim;
var accCredLimGrp = accCredLimDim.group(function(d) {return Math.floor(d/bin_width_credlim)*bin_width_credlim;});
And draw my bar chart:
var creditBar = dc.barChart("#creditDistrib");
creditBar
.width(600)
.height(250)
.margins({top: 10, right: 50, bottom: 30, left: 50})
.dimension(accCredLimDim)
.group(accCredLimGrp)
.transitionDuration(500)
.x(d3.scaleLinear().domain([minCredLim, maxCredLim]))
.xUnits(function(){return nb_of_bins_credlim;})
.elasticY(true)
.brushOn(true)
.xAxisLabel("Credit Limit")
I succeeded to do what I want initially just by customizing the yAxis().tickFormat() attribute of the bar chart, by dividing the tick value by the total number of rows being filtered at the moment:
creditBarChart.yAxis().tickFormat(function (d) {
return 100*d/all.value() + '%';
});
And I recompute these ticks every time a transition is being made, because my y-axis is elastic:
creditBar
.on("pretransition", function(){
creditBar.yAxis().tickFormat(function (d) {
if (!creditBar.hasFilter()){
return Math.trunc(100*d/all.value()) + '%';
}
});
});
As you can see, I don't update the ticks when the bar chart is being filtered. Indeed, when it is filtered I want the ticks to remain unchanged, as the y-axis should not change. However, because I am dividing the tick value by all.value() this rule cannot work when filtering the bar chart itself. The displayed percentages are obviously wrong.
This question is quite close to solving my problem: link but it is applicable only for categorical bar chart...
How can I display percentages on the y-axis ticks, that can change of values when filtering other charts and also when filtering the chart itself?
Is there a sort of all.value() that would be computed excluding the effect of filtering a specified chart?
Thanks!
Since you want the groupAll not to observe the filter on this chart, you should use the chart dimension's groupAll not the one on the crossfilter object. From the docs:
Note: a grouping intersects the crossfilter's current filters, except
for the associated dimension's filter. Thus, group methods consider
only records that satisfy every filter except this dimension's filter.
So, if the crossfilter of payments is filtered by type and total, then
groupAll by total only observes the filter by type.
That's kind of a mouthful, but I hope the intention is clear.
var accCredLimDim = ndx.dimension(function(d) { return d.acct_curr_crlimit;});
var all = accCredLimDim.groupAll();
Once you do that, you don't have to put an if statement in your tickFormat definition:
creditBar
.on("pretransition", function(){
creditBar.yAxis().tickFormat(function (d) {
return Math.trunc(100*d/all.value()) + '%';
});
});
The if statement was incorrect for a couple of reasons. First, there could be a filter on this chart and also filters on the other charts. Second, any accessor you call, like tickFormat, needs to return a value every time it is called. But this would return undefined if there was any filter on this chart, because that is the default return value in JS.

dc.js Can a Pie Legend be recentered after filtering

I would like to be able to recenter a Pie charts legend after it has been filtered. Slices/Legends will removed when filtering because we remove empty bins. I added a pretransition listener to chart2, but that seems to be to late because the legend y value is the previous value and not current.
.on('pretransition', chart => buildLegend (chart))
If Male is selected on the Gender Pie chart I want the 4 legend items on the Job Pie chart to be re-centered. Any suggestions?
You can see a jsFiddle example.
A little more digging around showed me how to reference and update SVG elements.
function recenterLegend(chart) {
chart.selectAll('g.dc-legend')
.attr('transform', function(d) {
let legendY = (300 - (chart.group().all().length * 16)) / 2;
let translate = 'translate(220,' + legendY + ')';
return translate ;
});
}
Here is the updated jsfiddle.

DC.js bar chart with date axis

I would like to create a bar chart based on dates in x-axis. Labels should be displayed as month (i.e. Jan, Jan'17 - preferred). Within my data I have always first date of following months, i.e. 01Jan, 01Feb, 01Mar. I have created a chart but I am not able to make it aligned.
var chart = dc.barChart("#" + el.id);
var chCategory = ndx.dimension(function(d) {return d[chCategoryName];});
chValues = chCategory.group().reduceSum(
return parseFloat(d[chValueName]);});
//set range for x-axis
var minDate = chCategory.bottom(1)[0][chCategoryName];
var maxDate = chCategory.top(1)[0][chCategoryName];
chart
.width(800)
.height(200)
.x(d3.time.scale().domain([minDate,maxDate]))
.xUnits(d3.time.months)
.dimension(chCategory)
.group(chValues)
.renderHorizontalGridLines(true)
// .centerBar(true) //does not look better
.controlsUseVisibility(true)
.ordinalColors(arrColors)
.transitionDuration(1000)
.margins({top: 10, left: 80, right: 5, bottom: 20})
I have already read post: dc.js x-axis will not display ticks as months, shows decimals instead
but I am not able to implement it in a way that will keep correct sorting for different years.
dc.js takes the domain pretty literally - the x axis stretches exactly from the beginning to the end, disregarding the width of the bars or their placement. It's a design bug.
Here are two workarounds.
keep bars centered and add padding
If you're using elasticX you can manually correct it like this:
chart.centerBar(true)
.xAxisPadding(15).xAxisPaddingUnit('day')
If you're just setting the domain manually, that's
minDate = d3.time.day.offset(minDate, -15);
maxDate = d3.time.day.offset(maxDate, 15);
align the ticks to the left of bars and correct the right side of the domain
You don't say what problem you run into when you don't center the bars. But I know the right bar can get clipped.
If you want the elasticX effect, you can implement it manually like this, offsetting the right side by a month (example):
function calc_domain(chart) {
var min = d3.min(chart.group().all(), function(kv) { return kv.key; }),
max = d3.max(chart.group().all(), function(kv) { return kv.key; });
max = d3.time.month.offset(max, 1);
chart.x().domain([min, max]);
}
chart.on('preRender', calc_domain);
chart.on('preRedraw', calc_domain);
Or without elasticX that's just:
maxDate = d3.time.month.offset(maxDate, 1);

D3.js: calculate x-axis time scale for bar graph?

I have the following dataset:
var data = [
{
"air_used": 0.660985,
"datestr": "2012-12-01 00:00:00",
"energy_used": 0.106402
},
{
"air_used": 0.824746,
"datestr": "2013-01-01 00:00:00",
"energy_used": 0.250462
} ...
]
And I want to draw a bar graph (for air_used) and line graph (for energy_used) that look like this:
My problem is that at the moment, with the x-scale I'm using, the graph looks like this - basically the bars are in the wrong position, and the last bar is falling off the chart:
Here is a JSFiddle with full code and working graph: http://jsfiddle.net/aWJtJ/4/
To achieve what I want, I think I need to amend the x-scale so that there is extra width before the first data point and after the last data point, and so that the bars are all shifted to the left by half the width of each bar.
Can anyone help me figure out what I need to do with the x-scale?
I've tried adding an extra month to the domain - that stops the last bar falling off the end of the graph, but it also adds an extra tick that I don't want, and it doesn't fix the position of the line graph and ticks.
If possible I want to continue to a time scale for the x-axis, rather than an ordinal scale, because I want to use D3's clever time-based tick formatters and date parsers, e.g. xAxis.ticks(d3.time.weeks, 2).
Expand your domain to be +1 and -1 month from the actual extent of your data. That will pad the graph with the extra months on either side and then update the bar width to add 2 to the count of data elements.
var barRawWidth = width / (data.length + 2);
See this fiddle: http://jsfiddle.net/reblace/aWJtJ/6/
If you want to hide the lower and upper boundary months, you can hack it like this: http://jsfiddle.net/reblace/aWJtJ/7/ by just adding and subtracting 20 days instead of a whole month, but there are probably more elegant ways to do it.
var xExtent = d3.extent(data, function(d) { return d.date; });
var nxExtent = [d3.time.day.offset(xExtent[0], -20), d3.time.day.offset(xExtent[1], 20)];
x.domain(nxExtent);
As pointed out in the comments, I think the best approach is to use d3.scale.ordinal. Note that using it doesn't prevent you from using d3.time parsers, but you need to take into account the bar width to align the line with the bars.
An example solution is here:
http://jsfiddle.net/jcollado/N8tuR/
Relevant code from the solution above is as follows:
// Map data set to dates to provide the whole domain information
var x = d3.scale.ordinal()
.domain(data.map(function(d) {
return d.date;
}))
.rangeRoundBands([0, width], 0.1);
...
// Use x.rangeBand() to align line with bars
var line = d3.svg.line()
.x(function(d) { return x(d.date) + x.rangeBand() / 2; })
.y(function(d) { return y(d.energy_used); });
...
// Use x.rangeBand() to set bar width
bars.enter().append("rect")
.attr("class", "air_used")
.attr("width", x.rangeBand())
...
Note that date parsing code has been moved up to have d.date available when creating the x scale. Aside from that, d3.time statements have not been modified at all.

Display x axis properly on stacked bar chart

Hey so I'm having difficulty with the positioning of my stacked bar chart. It's showing up, I'm just having difficulty declaring it's x axis. Here is the jsfiddle: http://jsfiddle.net/E2HST/
var xTimeScale = d3.time.scale().
domain([new Date(data[0].date), d3.time.day.offset(new Date(data[data.length - 1].date), 1)])
.range([0, width]);
is obviously part of the problem, I pulled code and have unfortunately fallen into the trap of not fully understanding it.
var bars = svg.selectAll(".bar")
.data(data).enter()
.append("g")
.attr("class","bar")
.attr("transform", function(d){
return "translate("+xTimeScale(d.date)+",0)"
})
I've tried swapping in d.year for d.date seeing as there is no more d.date but it's throwing up errors. Any help would be greatly appreciated.
The simple answer is that the objects in your data array do not have a date key, so your xTimeScale domain is undefined. An easy way to correct this would be to create this key for each data item:
data.forEach( function(d) { d.date = new Date(d.year, 0, 1); });
Which creates the date as January 1st of the year variable. This basically solves your x-axis problem.
I would, however, suggest that your data would be better suited to using an ordinal scale, since you only have yearly data.
A couple of other small things:
Your x-axis definition has way too many ticks, consider changing this
Consider adding css styles for .axis elements, to improve readability
An updated fiddle with these slight changes is at http://jsfiddle.net/E2HST/1/

Resources