NVD3 stacked bar chart does not show x-axis properly - javascript

I am trying to make a stacked bar chart with NVd3 but unfortunately the x-axis does not show properly. I want to show the year from 1999 to 2014 in the x-axis but this is what i get.
It seems that nvd3 is grouping all the values for the separate years together.
Javascript code
var data1 = [{}],
deaths = 0;
console.log(data1);
d3.csv('data/CENS-R1/ageGroups.csv', function(data) {
for (var i = 0; i < 12; i++) {
// setup a new entry for that age group
data1[i] = {
key: "1",
values: []
}
var v = i * 16;
// go through all the data
for (var j = 0; j < data.length; j++) {
// check if i equals the correct entries
if (0+v <= j && j < 16+v) {
data1[i].key = data[j].Age;
data1[i].values.push(
{
"x": (new Date()).getTime(parseInt(data[j]).Year),
"y": parseInt(data[j].Deaths)
}
);
}
}
}
});
console.log(data1);
nv.addGraph(function() {
var chart = nv.models.multiBarChart();
// format x-axis
chart.xAxis.tickFormat(function(d) { return d3.time.format('%Y')(new Date(d)) });
chart.yAxis
.tickFormat(d3.format(',.1f'));
d3.select('#stacked-chart svg')
.datum(data1)
.transition()
.duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
CSV file sample
CENS-R1,1,1999,1999,4390
CENS-R1,1,2000,2000,4354
CENS-R1,1,2001,2001,4188
Any help would be appreciated.

So apparently my function for parsing the date was wrong. instead of creating a new date with "x": (new Date()).getTime(parseInt(data[j]).Year) i used the Date.parse() function and that seemed to work.

Related

Two chart forming instead of one chart

I am making a doughnut chart using canvas js. I am using a custom js code where I am taking a response from XML and then pointing the data points
Here when I am changing the type of chart to "line" the graph is behaving as it should but when I am changing the chart type to “pie” or “doughnut” so now instead of one chart it is giving me two charts. How it working could someone please through a light?
My code is
$scope.loadChartValue = function (data, scopes) {
scopes.data_id = [];
scopes.legend_text = "";
scopes.inner_chart_data = [];
for (var i = 0; i <= data.length; i++) {
var arrayvalue = data[0].data[i]._attr;
if (existsInArray(scopes.data_id, arrayvalue.label._value) == false) {
scopes.data_id.push(arrayvalue.label._value);
}
}
for (var i = 0; i < scopes.data_id.length; i++) {
scopes.inner_chart_data = [];
for (var j = 0; j <= data.length; j++) {
if (data[0].data[j]._attr.label._value == scopes.data_id[i]) {
scopes.inner_chart_data.push({ label: data[0].data[j]._attr.label._value, y: data[0].data[j]._attr.value._value });
scopes.legend_text = data[0].data[j]._attr.label._value;
}
}
scopes.dataset.push(
{
type: "doughnut",
markerType: "circle",
markerSize: scopes.markersize,
color: scopes.chart_color_value[i],
showInLegend: true,
name: scopes.legend_text,
legendText: scopes.legend_text,
dataPoints: scopes.inner_chart_data
}
);
}
scopes.data_length = data.length / scopes.data_id.length;
}
Line, Column and other chart-types supports multi-series whereas pie/doughnut is single series charts.
You are creating multiple data-series instead of 1 data-series with multiple dataPoints. Creating single series with multiple dataPoints instead of multiple dataSeries will work fine.

JQPlot not using the correct dates

I'm drawing a graph using jqplot but it's plotting against the wrong date. see the code snippet and image below.
else if(rtype === "DATE AXES"){
$scope.pl = [[]];
for (var i = 0; i < plotVal.length; i++) {
console.log(plotVal[i].x+", "+plotVal[i].y);
$scope.pl.push([new Date(plotVal[i].x), plotVal[i].y]);
}
var data = $scope.pl;
console.log("data: ");
console.log(data)
jQuery.jqplot("chartdiv", [data],
{
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
}
},
series:[{color:'#5FAB78', markerOptions:{style:'square'}}],
});
}
Any idea what's wrong?
Found the problem. It's the pl array in the code; passed an empty value into it first, so it distorted the arrangement
$scope.pl = [[]];
was suppoed to be:
$scope.pl = [];

C3.js "Uncaught Error: Source data is missing a component at (1,844)!"

I am using C3.js and Electron (Atom Shell) to make a desktop application for data visualization. I am having trouble to feed my data into C3. I have a DataArray that contains all the coordinates: DataAray = [ [x1,y1] , [x2,y2] , [x3,y3],...].
I use the following code to break it into an xData array and a yData array:
xData = [];
yData=[];
xData.push('data1_x');
yData.push('data1');
for (var i = 0; i < DataArray.length ; i++){
xData.push (DataArray[i][0]);
yData.push (DataArray[i][1]);
}
var chart = c3.generate({
bindto: '#chart',
data: {
xs: {
data1: 'data1_x',
},
columns: [
x,
y
],
type: 'scatter'
}
});
but when I run the application, I get this error:
"Uncaught Error: Source data is missing a component at (1,844)!", source: PATH/To/c3-0.4.10/c3.min.js (2)
and the graph is not plotted at all. If I change the for loop to
for (var i = 0; i < 843 ; i++)
however, it does plot the graph.
I was using Plotly before, and I used to run the exact same code to prepare the data for Plotly, and it worked just fine. What is the problem here? Also, is there a way to ask C3 to ignore errors in the data? For example, if there is a null at one of the points, is there a way for C3 to plot the graph anyways?
I don't know if there is a way to configure C3 to ignore null or undefined values. Try ignoring the null/undefined values so that C3 can plot the graph.
for (var i = 0; i < DataArray.length ; i++) {
// if the value is not undefined or null, push to array
if (DataArray[i][0] !== undefined && DataArray[i][0] !== null) {
xData.push (DataArray[i][0]);
} else {
// push 0 to signify no data
xData.push(0);
}
...
}
C3 will ignore null values. But you will get this error when a value is undefined. The answer from TonalLynx will work. Or you could change undefined values to null.
for (var i = 0; i < DataArray.length ; i++) {
// if the value is undefined, push null to array
if (DataArray[i][0] === undefined) {
xData.push (null);
} else {
xData.push (DataArray[i][0]);
}
...
}
c3 has an internal function that can help do that
c3_chart_internal_fn.convertColumnsToData = function (columns) {
var new_rows = [], i, j, key;
for (i = 0; i < columns.length; i++) {
key = columns[i][0];
for (j = 1; j < columns[i].length; j++) {
if (isUndefined(new_rows[j - 1])) {
new_rows[j - 1] = {};
}
if (isUndefined(columns[i][j])) {
throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
}
new_rows[j - 1][key] = columns[i][j];
}
}
return new_rows;
};

dc.js graph won't show line and y axis values

Working off the example here, I'm using my own dataset in a csv to attempt to display a simple line graph. However, no matter how I create the 'groups' for the lineChart, it won't show any actual line on the graph, nor any y values on the axis. I'm parsing the time correctly because the brush works as expected on the graph and the x axis has the proper time labels.
d3.csv('weatherLogMod.csv', function(data) {
var parseDate = d3.time.format("%Y/%m/%d %H:%M");
data.forEach(function(d) {
d.absHumidity = ((6.112 * Math.exp((17.67 * +d.Temperature)/(+d.Temperature + 243.5)) * 2.1674 * +d.Humidity.replace(/[",%]/g, ''))/(273.15 + +d.Temperature));
d.date = parseDate.parse(d.Time);
d.warmth = +d.Temperature;
});
var instance = crossfilter(data);
var dateDim = instance.dimension(function(d) { return d.Time; });
var tempGroup = dateDim.group().reduceSum(function(d) {return d.warmth;});
var minDate = dateDim.bottom(1)[0].date;
var maxDate = dateDim.top(1)[0].date;
var tempChart = dc.lineChart("#chart-line-hitsperday");
tempChart
.width(500).height(200)
.dimension(dateDim)
.group(tempGroup)
.x(d3.time.scale().domain([minDate,maxDate]));
dc.renderAll();
});
I can't find what I'm doing wrong; in the console, doing tempGroup.all() gives me an array full of temperature-date value:keys, so it seems like it should be working?
Here's a screenshot of my problem.
After some trial and error I figured it out;
var dateDim = instance.dimension(function(d) { return d.Time; });
should be:
var dateDim = instance.dimension(function(d) { return d.date; });
and it works fine.

NVD3 : Display different values on X axis as compared to the data

I am creating a scattered Graph using NVD3 using the code they have provided in their limited documentation. I have created a Scatter graph function that loops over a JSON and pushes the values to the data array.
Now I have 2 values for x axis in my Json , x and run Number. What i want is that the graph should be plotted for the value "x" (which have equal gaps) but it should display values of Run Number on the x axis (which have unequal gaps). We want to do this to make the graph more symmetric, as it is not important for us to display the gaps in graph accurately.
What i did was create a new Array xAxisValue and push the Run Numbers onto it while we loop the JSON to get values. values for x are pushed onto the data array ,
Then using
chart.xAxis.axisLabel('Run No.').tickFormat(d3.format('0d')).tickValues(
xAxisValue);
I set the Tick Values to the xAxisValue (run Number) and then pass the data variable to the draw chart function
d3.select('#chart svg').datum(myData).call(chart);
But this does not seem to work. My Axis is blank and hovering over a value displays the tool tip displays values of x instead of run number.
Because we are dynamically updating the graph i have separated the add Graph and upgrade graph function
Here is the code
function addGraph() {
var jsons = [];
chart = nv.models.scatterChart().showDistX(true).showDistY(true)
.transitionDuration(350).color(d3.scale.category10().range());
chart.tooltipContent(function(key) {
return '<h3>' + key + '</h3>';
});
chart.scatter.onlyCircles(false);
var myData = scatterData(2, 11, jsons);
d3.select('#chart svg').datum(myData).call(chart);
// add zoom handler
nv.utils.windowResize(chart.update);
return chart;
}
Upgrade Graph Function
function upgradeGraph() {
minValue = 1000000, maxValue = 0, minValueY = 100000000, maxValueY = 0;
var jsons = [];
d3.select('svg').text('');
if ($("#check2").is(':checked')) {
jsons.push("charge_ONTk_Barrel_L2_mpv.json");
}
if ($("#check1").is(':checked')) {
jsons.push("charge_ONTk_Barrel_L1_mpv.json");
}
if ($("#check3").is(':checked')) {
jsons.push("charge_ONTk_Barrel_L3_mpv.json");
}
var myData = scatterData(2, 11, jsons);
chart.xAxis.axisLabel('Run No.').tickFormat(d3.format('0d')).tickValues(
xAxisValue);
chart.yAxis.axisLabel('S/N (mpv)').tickFormat(d3.format('.04f'));
for (var i = 0; i < xAxisValue.length; i++) {
console.log("Run Number: " + xAxisValue[i]);
}
console.log("Min Y: " + minValueY + " Max Y " + maxValueY);
chart.forceX([ minValue - 2, maxValue + 2 ]);
chart.forceY([ minValueY - 3, maxValueY + 3 ]);
d3.select('#chart svg').datum(myData).call(chart);
// add zoom
addZoom({
xAxis : chart.xAxis,
yAxis : chart.yAxis,
yDomain : chart.yDomain,
xDomain : chart.xDomain,
redraw : function() {
chart.update();
},
svg : chart.svg
});
nv.utils.windowResize(chart.update);
return chart;
}
And the ScatterData Function
function scatterData(groups, points, jsons) {
var data = [];
data.push({
key : 'Error',
values : [],
color : '#FBEC5D'
});
data.push({
key : 'Bin Content ',
values : [],
color : '#0D4F8B'
});
for (var i = 0; i < jsons.length; i++) {
xAxisValue = [];
var jsonURL = jsons[i];
var xmlhttp = new XMLHttpRequest();
var url = "alljsons/" + jsons[i];
var parameters = location.search;
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
var jsonName = jsonURL.split(".");
var temp = jsonName[0];
var value = myArr[temp];
// $(".title" + loop).html(temp);
for ( var i in value) {
if (value[i].run > maxValue) {
maxValue = value[i].x;
}
if (value[i].run < minValue) {
minValue = value[i].x;
}
if (value[i].y > maxValueY) {
maxValueY = value[i].y;
}
if (value[i].y < minValueY) {
minValueY = value[i].y;
}
xAxisValue.push(value[i].run);
data[1].values.push({
x : value[i].x,
y : value[i].y,
size : 6 // Configure the size of each scatter point
,
shape : "circle"
});
var err = value[i].y - value[i].yErr;
if (err < 0) {
err = 0;
console.log("error: " + err);
}
data[0].values.push({
x : value[i].x,
y : err,
size : 6 // Configure the size of each scatter point
,
shape : "triangle-down"
});
}
}
};
xmlhttp.open("GET", url, false);
xmlhttp.send();
}
return data;
}
Here is the Output i am getting
If I understand your question correctly:
For the x-axis ticks, I would use D3's axis.tickformat function. You could create a function mapXToRunNumber(x) that takes an x value and returns a run number (you seem to be close to having this already). Then, you would use: chart.xAxis.tickFormat(mapXtoRunNumber);
For the tooltip to also show the same value as the x-axis, you would use the nvD3 function chart.interactiveLayer.tooltip.headerFormatter(mapXToRunNumber).

Categories