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.
Related
I have existing charts that displays data for a full day 12:00am - 12:00am.
Now required to change one chart forward to display 4:00am - 4:00am.
I have managed to shift the x axis labels (.add(4, 'hours')) but the chart data is still in the same position.
How do I shift the charted data forward 4 hours?
Limited scope to change global variables as this will impact other charts.
var getChartSeries = function(response, chart_series_data) {
var lines = response.graph_data.lines;
for (var i=0; i<lines.length; i++) {
var series = lines[i];
var dateFormat = graphDateFormat;
if (chartIntraday) dateFormat = 'HH:mm:ss';
var currSeriesData = [];
for (var j=0; j<series.data.length; j++) {
var row = series.data[j];
var yValue = parseFloat(row[1]);
var point = {
x: moment(row[0], dateFormat).add(4, 'hours').valueOf(),
y: yValue,
displayValue: row[3]
};
currSeriesData.push(point);
}
// Set the series name, legend label, and the line identifier
var name = formatLegendLabel(series.display_name, response);
var label = response.label;
if (response.display_name != undefined && response.display_name != '') label = series.display_name + ' : ' + label;
By default chart adjusts extremes to the provided data. To display these few hours before the first point use xAxis.min property.
Live demo: http://jsfiddle.net/kkulig/xqdqooh9/
API reference: https://api.highcharts.com/highcharts/xAxis.min
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.
I want to set up a d3 quadtree using data which does not have columns labelled x and y, but with some other labels. Reading the quadtree docs I thought I could do it like this:
var data = [{"a":6,"b":99.0},{"a":12,"b":227.0},{"a":2,"b":43.0},{"a":23,"b":32.0}];
var xname = "a";
var yname = "b";
var quadtree = d3.geom.quadtree(data)
.x(function(d) {return d[xname]; })
.y(function(d) {return d[yname]; });
But when I run this code I get an error:
TypeError: d3.geom.quadtree(data).x is not a function. (In 'd3.geom.quadtree(data).x(function(d) {return d[xname]; })', 'd3.geom.quadtree(data).x' is undefined)
How can I set up the quadtree to use different x and y labels? (Obviously I could change the data to use "x" and "y" but there are reasons I don't want to do that.)
Don't create your quadtree passing it data
e.g :
var data = [{"a":6,"b":99.0},{"a":12,"b":227.0},{"a":2,"b":43.0},{"a":23,"b":32.0}];
var xname = "a";
var yname = "b";
var quadtree = d3.geom.quadtree(/* nothing here */)
.x(function(d) {return d[xname]; })
.y(function(d) {return d[yname]; });
data binding must append later
d3.selectAll('circle').data(quadtree(data))
.append('circle');
I'm a newbie in javascript but a few weeks back just delved into d3.js trying
to create a spatio-temporal visualisation.
What I want to achieve is something like this (https://jsfiddle.net/dmatekenya/mz5fxd44/) based on code shown below:
var w1 = ["Dunstan","Mercy","Lara","Khama"];
var w2 =["August 1,2013","August 2,2013","August 3,2013"]
var text = d3.select("body")
.attr("fill","red")
.text("Dunstan")
.attr("font-size", "50px");
var j = 0;
var transition = function() {
return text.transition().duration(500).tween("text", function() {
var i = d3.interpolateString(w1[j], w1[j + 1]);
return function(t) {
this.textContent = i(t);
};
}).each('end', function() {
j += 1;
if (!(j > w1.length)) return transition();
});
};
transition();
However, instead I want to use date string ( like w2 in the code snippet above). When I do this d3 interpolates the numbers embedded in the string as well and the output isn't what I'm looking for. I need help on how I can somehow create a custom interpolator which can interpolate date string while ignoring numbers in them. I know from d3 documentation (https://github.com/mbostock/d3/wiki/Transitions#tween) thats its possible to push a custom interpolator into the d3 array of interpolators but I have tried and still cannot get it to work.
Kindly need your help.
Maybe you need d3.scaleQuantize().
For instance:
var color = d3.scaleQuantize()
.domain([0, 1])
.range(["brown", "steelblue"]);
color(0.49); // "brown"
color(0.51); // "steelblue"
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).