How to display yearly values on xAxis in Highcharts - csv

I guess this is somewhat of a stupid question. But I am struggling since quite a while with this, not finding what the right way of data formatting is for my data.
I have yearly data like this, which I want to have displayed as such - 2001, 2002, 2003, ...:
time,lat,lon,Npp_1km
Date.UTC(2001/1/1),15,-90,1.266112766
Date.UTC(2002/1/1),15,-90,1.166646809
Date.UTC(2003/1/1),15,-90,1.020591489
Date.UTC(2004/1/1),15,-90,1.016010638
Date.UTC(2005/12/31),15,-90,1.08053617
Date.UTC(2006/12/31),15,-90,1.181195745
and my Highcharts code which looks like this:
xAxis: {
labels: {
style: {
color: "#666666"
},
x: 0
},
gridLineWidth: 1,
gridLineDashStyle: 'Dot',
tickWidth: 0,
type: 'datetime'
},
But the xAxis doesn't display the years but instead some "00:00:00.001".
I have tried many different formats for the timestamp - "2001-1-1", "2001/1/1", "1/1/2001", "1-1-2001", "Date.UTC(2001/1/1)". I have changed the "dateTimeLabelFormats" as well. But all in vain. It doesn't spit out "2001 - 2002 - 2003 - 2004".
Here is a fiddle.
What is the right way to achieve this? Thanks for any hints!

You had problems with parsing your data. All of your x values was not correct - that is the reason of your issue. You need to parse it a little bit different if you want to get the correct data for your chart:
$.get('data.csv', function(data) {
var temp = []
// Split the lines
var lines = data.split('\n');
// For each line, split the record into seperate attributes
$.each(lines, function(lineNo, line) {
var items = line.split(',');
if (lineNo !== 0) {
items[0] = items[0].substring(items[0].indexOf('(') + 1, items[0].indexOf(')'));
var x = new Date(items[0]),
y = parseFloat(items[3]);
if (!isNaN(y)) {
x = x.getTime();
options.series[0].data.push([x, y]);
}
}
});
Here you can see an example how it can work:
http://jsfiddle.net/pcpq6mtr/4/
Regards,

A simple solution can be put categories in xAxis if the time is fixed.
xAxis {
categories:[2001,2002,2003,2004,2005,2006]
}
If the time is not fixed. categories need to be calculated dynamically.

Related

How to add legend for a bar chart with different colors in dc.js?

Below is the code snippet for a barchart with colored bars:
var Dim2 = ndx.dimension(function(d){return [d.SNo, d.something ]});
var Group2 = Dim2.group().reduceSum(function(d){ return d.someId; });
var someColors = d3.scale.ordinal().domain(["a1","a2","a3","a4","a5","a6","a7","a8"])
.range(["#2980B9","#00FFFF","#008000","#FFC300","#FF5733","#D1AEF1","#C0C0C0","#000000"]);
barChart2
.height(250)
.width(1000)
.brushOn(false)
.mouseZoomable(true)
.x(d3.scale.linear().domain([600,800]))
.elasticY(false)
.dimension(Dim2)
.group(Group2)
.keyAccessor(function(d){ return d.key[0]; })
.valueAccessor(function(d){return d.value; })
.colors(someColors)
.colorAccessor(function(d){return d.key[1]; });
How do I add a legend to this chart?
Using composite keys in crossfilter is really tricky, and I don't recommend it unless you really need it.
Crossfilter only understands scalars, so even though you can produce dimension and group keys which are arrays, and retrieve them correctly, crossfilter is going to coerce those arrays to strings, and that can cause trouble.
Here, what is happening is that Group2.all() iterates over your data in string order, so you get keys in the order
[1, "a1"], [10, "a3"], [11, "a4"], [12, "a5"], [2, "a3"], ...
Without changing the shape of your data, one way around this is to sort the data in your legendables function:
barChart2.legendables = function() {
return Group2.all().sort((a,b) => a.key[0] - b.key[0])
.map(function(kv) {
return {
chart: barChart2,
name: kv.key[1],
color: barChart2.colors()(kv.key[1]) }; }) };
An unrelated problem is that dc.js takes the X domain very literally, so even though [1,12] contains all the values, the last bar was not shown because the right side ends right at 12 and the bar is drawn between 12 and 13.
So:
.x(d3.scale.linear().domain([1,13]))
Now the legend matches the data!
Fork of your fiddle (also with dc.css).
EDIT: Of course, you want the legend items unique, too. You can define uniq like this:
function uniq(a, kf) {
var seen = [];
return a.filter(x => seen[kf(x)] ? false : (seen[kf(x)] = true));
}
Adding a step to legendables:
barChart2.legendables = function() {
var vals = uniq(Group2.all(), kv => kv.key[1]),
sorted = vals.sort((a,b) => a.key[1] > b.key[1] ? 1 : -1);
// or in X order: sorted = vals.sort((a,b) => a.key[0] - b.key[0]);
return sorted.map(function(kv) {
return {
chart: barChart2,
name: kv.key[1],
color: barChart2.colors()(kv.key[1]) }; }) };
Note that we're sorting by the string value of d.something which lands in key[1]. As shown in the comment, sorting by x order (d.SNo, key[0]) is possible too. I wouldn't recommend sorting by y since that's a reduceSum.
Result, sorted and uniq'd:
New fiddle.

Rotate node to look at another node

Cocos Creator - I have a node that I want to rotate towards another node, here is the code I'm using:
update: function (dt) {
this.rotate();
},
rotate: function () {
var diff = this.target.position - this.node.position;
var angle = Math.atan2(diff.x, diff.y);
this.node.rotation = cc.radiansToDegress(angle);
},
But it's not rotating at all, I tried to search the docs but couldn't find anything helpful.
var diff = this.target.position - this.node.position;
You're basically trying to subtract an object from an object. Check
{'x':2, 'y':3} - {'x':4, 'y':6}
in your JS console. The result is NaN
You need to subtract each dimension manually.
var diff = {
'x' : this.target.position.x - this.node.position.x,
'y':this.target.position.y - this.node.position.y
};
Apologies to necro this question, but since this is a top search result I just wanted to add that the problem here is that the signature of Math.atan2 takes it's coordinates backwards:
Syntax:
Math.atan2(y, x)
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2

D3 Timeline CSV Data

I am using the d3 Timeline plugin (https://github.com/jiahuang/d3-timeline) and I finally got it to where the viz can read my data. However, I now need to make it so that all entries for a particular student show on the same line. The viz is currently displaying each entry separately.
CSV data looks like this:
Start,End,Student,Event Type,tooltip
2015-May-27 20:08:15,2015-May-27 20:08:21,Student 338,Pretest,Student 338 spent 00:00:06 on Biological Chemistry test. Student scored 100%.
2015-May-27 20:08:21,2015-May-27 20:08:30,Student 338,Learning Path,Student 338 spent 00:00:09 on Biological Buffers Website.
2015-May-27 20:08:30,2015-May-27 20:08:34,Student 338,Learning Path,Student 338 spent 00:00:04 on Organic Molecules Textbook.
2015-May-27 20:08:34,2015-May-27 20:08:36,Student 338,Learning Path,Student 338 spent 00:00:03 on Nucleic Acid Structure and Function Textbook 2.
The viz file looks like this:
<script type="text/javascript">
window.onload = function() {
var width = 800;
var height = 700;
var parseDate = d3.time.format("%Y-%b-%d %H:%M:%S").parse; //With parseDate, I define what my time data looks like for d3
d3.csv("https://dl.dropboxusercontent.com/u/42615722/LeaP/biology-course2.csv", function(d){
return {
label : d.Student,
eventType: d["Event Type"],
times:[{"starting_time" : parseDate(d.Start),
"ending_time" : parseDate(d.End)}], //the timeline plugin is looking for a times array of objects with these keys so they must be defined.
info: d.tooltip
};
}, function(data) {
console.log(data);
function timelineRect() {
var colorScale = d3.scale.ordinal().range(['#ed5565','#ffce54','#48cfad','#5d9cec','#ec87c0','#ac92ec','#4fc1e9','#fc6e51','#a0d468','#656d78'])
.domain(['Pretest','Learning Path','Supplemental Info','Questions','Test Me','Remedial Page','Search Query','Recommended Reading','Search Results','Practice Questions']);
var chart = d3.timeline()
.colors( colorScale )
.colorProperty('event_type')
.rotateTicks(45)
.stack(); //necessary to unstack all of the labels
var svg = d3.select("#timeline1").append("svg").attr("width", width)
.datum(data).call(chart);
}
timelineRect();
});
}
</script>
</head>
<body>
<div>
<div id="timeline1"></div>
</div>
</body>
None of the examples define domain for this and, unfortunately, all of the example data is given in arrays, instead of from a CSV. How can I define the data so that each entry with the same student label will appear on the same timeline row?
Problem 1
You are not grouping your csv data this can be done like this:
What I mean is
//this will do the grouping
var k = d3.nest()
.key(function(d) {
return d.label;
}).entries(data);
var b = [];
//this will make it in the format expected by d3 time line
k.forEach(function(d) {
var ob = {};
ob.label = d.key;
ob.times = [];
b.push(ob);
d.values.forEach(function(v) {
ob.times.push(v.times);//collecting all the times
});
ob.times = [].concat.apply([], ob.times);
});
Problem 2
You have to define the tick format
.tickFormat({
format: d3.time.format("%d-%m"),
tickTime: d3.time.day,
tickInterval: 20,
tickSize: 6
})
Refer this for d3 time format
Your data set is very close on seconds and so the rectangle are coming very small..:( i tried my level best to span it up.. best of luck with it :)
Working code here
Hope this helps!

Customising Google Bar Chart Using Google App Script

I am currently having some issues configuring a simple graph using Google App Scripts. I seem to be unable to find the correct documentation in order to progress any further!
I have everything hooked up pulling data from a couple of spreadsheets, so that aspect is fine!
I see that there are various ways in order to customise the looks of a chart and there are tools available for example:
http://imagecharteditor.appspot.com/
http://code.google.com/apis/ajax/playground/?type=visualization
I wish to add colours to my bar charts like in this example
http://code.google.com/apis/ajax/playground/?type=visualization#image_multicolor_bar_chart
Additionally in the first link there are options to create sections using the range marker tool. I was hoping that with these tools I could copy the code across to use in my App Script Chart.
The only way I can see this working is using .setOption(string, object)
I've tried this...
var data = Charts.newDataTable()
.addColumn(Charts.ColumnType.STRING, 'Month')
.addColumn(Charts.ColumnType.NUMBER, 'Mark Achieved')
for(var x=0; x < ChartData.length;x++){
data.addRow(ChartData[x]);
}
data.build();
var chart = Charts.newColumnChart()
.setDataTable(data)
.setDimensions(1000, 600)
.setRange(0, 100)
.setTitle('Test Scores')
.setLegendPosition(Charts.Position.BOTTOM)
.setOption('options',{cht: 'bvs', chco: 'A2C180,3D7930', max: 100})
.build();
app.add(chart);
any help would be much appreciated!
EDIT
The options you are trying to use are applicable to the static image charts (which are now deprecated), and won't work with ColumnCharts. ColumnCharts color the bars by series, not by data point, so if you want multi-colored bars, you have to separate them out into different data series. I wrote a hack that does this (see on jsfiddle for the standard javascript version). My reading of the AppsScript implementation of the Visualization API seems to preclude using calculated columns in the DataViews, but it is possible that the documentation is incomplete here. Try creating a view like this:
// add one calculated column for each month
var dataViewDefinition = Charts.newDataViewDefinition().setColumns([0, {
type: Charts.ColumnType.NUMBER,
label: 'Mark Achieved',
calc: function (dt, row) {
if (dt.getValue(row, 0) == 'January') ? dt.getValue(row, 1) : null;
}
}, {
type: Charts.ColumnType.NUMBER,
label: 'Mark Achieved',
calc: function (dt, row) {
if (dt.getValue(row, 0) == 'February') ? dt.getValue(row, 1) : null;
}
}/*...*/]);
It is probable that this needs to be tweaked, and possible that it won't work at all, in which case you would have to either change the query of the spreadsheet or rearrange the structure of the spreadsheet.
As far as adding the ranges to the chart, can you elaborate more on what you would like those to look like?

Creating a line graph with highcharts and data in an external csv

I've read through the Highcharts how-to, checked the demo galleries, searched google, read the X amount of exact similar threads here on stackoverflow yet I cannot get it to work.
I'm logging data in a csv file in the form of date,value.
Here's what the date looks like
1355417598678,22.25
1355417620144,22.25
1355417625616,22.312
1355417630851,22.375
1355417633906,22.437
1355417637134,22.437
1355417641239,22.5
1355417641775,22.562
1355417662373,22.125
1355417704368,21.625
And this is how far I've managed to get the code:
http://jsfiddle.net/whz7P/
This renders a chart, but with no series or data at all. I think I'm fudging things up while formatting the data so it can be interpreted in highcharts.
Anyone able to give a helping hand?
So, you have the following data structure, right ?
1355417598678,22.25
1355417620144,22.25
1355417625616,22.312
1355417630851,22.375
1355417633906,22.437
1355417637134,22.437
1355417641239,22.5
1355417641775,22.562
1355417662373,22.125
1355417704368,21.625
Then you split it into an array of lines, so each array item is a line.
Then for each line you do the following.
var items = line.split(';'); // wrong, use ','
But there ins't ; into the line, you should split using ,.
The result will be a multidimencional array which each item is an array with the following structure. It will be stored in a var named data.
"1355417598678","22.25" // date in utc, value
This is the expected data for each serie, so you can pass it directly to your serie.
var serie = {
data: data,
name: 'serie1' // chose a name
}
The result will be a working chart.
So everything can be resumed to the following.
var lines = data.split('\n');
lines = lines.map(function(line) {
var data = line.split(',');
data[1] = parseFloat(data[1]);
return data;
});
var series = {
data: lines,
name: 'serie1'
};
options.series.push(series);
Looking at your line.split part:
$.get('data.csv', function(data) {
// Split the lines
var lines = data.split('\n');
$.each(lines, function(lineNo, line) {
var items = line.split(';');
It looks like you are trying to split on a semi-colon (;) instead of a comma (,) which is what is in your sample CSV data.
You need to put
$(document).ready(function() {
in the 1st line, and
});
in the last line of the javascript to make this work.
Could you upload your csv file? Is it identical to what you wrote in your original post? I ran into the same problem, and it turns out there are errors in the data file.