NVD3 X axis incorrect ordering (dates) - d3.js

I'm trying to visualize 2 series but when I visualize them together, the dates don't go in sequential order anymore.
Here is the fiddle: http://jsfiddle.net/hohenheim/6R7mu/21/ Notice the weird x-axis.
Is there a way to fix the x axis on nvd3?
The data looks like this:
data1 = [{
"date": 1396828800,
"impressions": 49145385
}, {
"date": 1396915200,
"impressions": 46704447
} ....

The NVD3 "multiBarChart" uses an ordinal (category) scale, so it will only display the x-values you give it, in the order in which they are added to the scale. Because your two series only partially overlap on the x axis that's causing problems.
Unlike other NVD3 chart types, the multiBarChart doesn't give you the option of setting your own scale -- it needs to use an ordinal scale in order to generate even widths for the bars. However, you can set the x domain (the list of categories to use for each bar), by calling chart.xDomain(arrayOfXValues).
The array will need to be an ordered array of Date values that spans your data. In order to generate it, you'll need the d3 time intervals range functions. You might also need the d3.extent function to find your max and min values.

Related

Use dates as numbers, but format them as dates in UI

Let's take this example.
https://d3fc.io/examples/series-canvas-candlestick/
It defines X scale as a time scale.
const xScale = d3
.scaleTime()
.domain(fc.extentDate().accessors([d => d.date])(data));
To prevent multiple tick to date conversion in my zoom handler, I'd like to always work with number, but keep UI showing these numbers as dates. So, I change the code above to linear scale.
const xScale = d3
.scaleLinear()
.domain(fc.extentLinear().accessors([d => d.date.getTime()])(data));
Everything works fine, but now I have an X scale showing numbers instead of dates. The question is, how to add mapper or formatter that would show these numbers as dates in UI? I see some examples of d3.tickFormat, but not sure how to apply it in d3fc.
https://observablehq.com/#d3/axis-ticks
You supply your scales to the D3FC cartesian chart, which then couples these with the axes that it creates for you.
As mentioned in the documentation the chart exposes the properties of the X and Y axes with an x and y prefix. So, if you want to change the tick format for the X axis, which you would typically do via the tickFormat property, you instead do the following:
var chart = fc.chartCartesian(
d3.scaleLinear(),
d3.scaleLinear()
)
.xTickFormat(/* ... formatter goes here */);

Plotting unique values from a single column in a dc.js box plot

What i am trying to do is plot data from a single column as a box plot in dc.js
My aim here is outlier detection. When i plot the unique numerical values from a column, i should be able to spot the outliers on the box plot.
Now i am having a tough time achieving this. I was able to implement the outlier detection for two columns using the scatter plot. But it seems the same way of defining groups and dimensions does not work with the box plot. So i will have to write a map reduce function to do that.
The box plot should take the numerical dimension as the chart Dimension but not sure how to calculate the chart group for the unique counts.
var groupReduce = dim1.group().reduce(
function(p,v) {
p.push(v.num_donors);
return p;
},
function(p,v) {
p.splice(p.indexOf(v.num_donors), 1);
return p;
},
function() {
return [];
}
);
I tried reductio as well but not sure if exception aggregation is the feature i am looking for. I just want to plot the unique values on a box plot.
Here is the JSfiddle of what i have so far
https://jsfiddle.net/anmolkoul/w5fq73ys/1/
And this is what i am hoping to build for a single numerical columns (in this case num_donors):

Multi line ordinal chart in dc.js

I am stuck on a problem here. Could be simple though but i am having a tough time figuring it out. I want to show multiple lines on a dc composite chart.
My data is like this:
{ Name: Mike, mark1: 26.9, mark2: 62.3 },
{ Name: John, mark1: 23.5, mark2: 60.3 },
{ Name: Firen, mark1: 24.3, mark2: 62.5 }
I need the name plotted against X axis and mark1 and mark2 plotted as lines against the Y axis. I found a fiddle here which uses a linear scale to achieve the same result. http://jsfiddle.net/anmolkoul/mzx6mnru/3/
But it uses a linear scale as the base dimension is numerical. My base dimension is a string and hence not working with the same code. I figured it is due to the scale definition that i am using. Here is the fiddle that i need help with: http://jsfiddle.net/anmolkoul/pjLoh1az/1/
I have currently defined my x axis as
.x(d3.scale.ordinal().domain(nameDimension))
.xUnits(dc.units.ordinal)
I think this is where it is going wrong. I have two supplementary questions as well:
Once this is done, how to assign different colors to the lines ( it should reflect in the legend as well)
I was taking a look at the dc.js series chart, what does this line of code do?
runDimension = ndx.dimension(function(d) {return [+d.Expt, +d.Run]; });
Does it pivot the two dimensions? or is it just a quicker way of creating two crossfilter dimensions.
Thank you for the help!`
You can get the ordinal values with :
nameDimension.top(Infinity).map(function(d) {return d.Name}))
which returns ["Mike", "John", "Firen"] , then use it for the ordinal domain.
But it's not necessary, it's calculated automatically :
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
For colors, you can use :
dc.lineChart(lineChart1).group(mark1Group,"Mark 1").colors("#FF0000")
Here is a fiddle with those modifications : http://jsfiddle.net/1exo25u9/

DC.js Choropleth filtering Issue

I am trying to filter data on my choropleth chart from a bargraph. Strange thing is that it is not showing correct value on selecting a bar from the accompanying bar chart.
Here is the jsfiddle: https://jsfiddle.net/anmolkoul/jk8LammL/
The script code begins from line 4794
If i select WIN004 from the bar chart, it should highlight only five states and the tooltip should reflect the values for the data. Some states are highlighted for whom WIN004 does not exist.
I changed the properties of the choropleth from
.colors(d3.scale.quantize().range(["#F90D00", "#F63F00", "#F36F01", "#F09E01", "#EDCB02", "#DDEA03", "#ADE703", "#7EE404", "#50E104", "#24DE05", "#05DB11"]))
.colorDomain([-1, 1])
To
.colors(d3.scale.linear().range(["green", "white", "red"]))
.colorDomain([-2, 0, 2])
But i get a lot of white states where its hard to discern what has been highlighted. The tool tip for some white-ed-out states show -0.00 :/
Here is the fiddle http://jsfiddle.net/anmolkoul/jk8LammL/1/
So i guess either its a problem with my color range or how my data is getting parsed.
I would ideally like to specify the data ranges in the .colorDomain based on the top and bottom values of the riskIndicator dimension. My functions are not working though. Should i use d3.max or riskIndicator.top here?
EDIT:
I got the color domain dynamic by using the min and max values but still the graph is not performing as expected? Could this be an issue with the geochoropleth chart? I further took a working geochoropleth example and ported my data to it and even that gave me the same issue of representing data incorrectly. I thoughit could be a data problem but i validated using a couple of good BI tools and their map charts displayed data correctly.
Could this be an issue with the dc choropleth?
Thank you.
Anmol
This has the same root cause as the issue in this question:
Crossfilter showing negative numbers on dc.js with no negative numbers in the dataset
In short, floating point numbers don't always cancel out to zero when added and subtracted. This "fake group" will ensure they snap to zero when they get close:
function snap_to_zero(source_group) {
return {
all:function () {
return source_group.all().map(function(d) {
return {key: d.key,
value: (Math.abs(d.value)<1e-6) ? 0 : d.value};
});
}
};
}
Added it to the FAQ!

Custom order of x axis in D3.js

I have these labels for axis X:
1..2..3..4..5..6..etc
But I need the custom order:
3..2..5..1..6..4..etc
Even if I give the array in such custom order to d3, it automatically orders it like in the first example.
I'm using nv.models.lineChart().
The exact dump of my values:
[{"values":[{"label":18,"value":12},{"label":19,"value":412},{"label":20,"value":441},{"label":21,"value":920},{"label":22,"value":944},{"label":23,"value":144},{"label":0,"value":0},{"label":1,"value":18},{"label":2,"value":0},{"label":3,"value":7},{"label":4,"value":4},{"label":5,"value":12},{"label":6,"value":0},{"label":7,"value":0},{"label":8,"value":0},{"label":9,"value":9},{"label":10,"value":9},{"label":11,"value":32},{"label":12,"value":27},{"label":13,"value":31},{"label":14,"value":0},{"label":15,"value":30},{"label":16,"value":3},{"label":17,"value":844}],"key":"Buyings count hourly","color":"#53d488"}]

Resources