Incorrect values on Highcharts (compared to input) - javascript

I have a (Highcharts) graph with a percentage over time. The input for my series looks something like:
series: [{
name: "Percentage",
data: [
[1472515200000, 49],
[1472601600000, 48.83],
[1472688000000, 49.6],
[1472774400000, 48.77]
]
}]
However on the actual chart (areaspline) I get different values:
30 Aug, 48.91
31 Aug, 49.36
1 Sep, 49.6
2 Sep, 48.87
Not entirely sure why this is the case, I'm assuming it's because the graph has a datetime type and it's figuring out the average over time. Is there a way I can make the values exact as they are input? Couldn't find anything in docs
Thanks for any ideas/help/advice.
Upon further research, it seems like it's not so much a Highcharts problem but a React one. I seem to be getting different values on each render. Will look into this further and update for the curious.
Problem seemed to be related to React re-rendering and therefore recalculating my percentage values - not a Highcharts issue. Thanks for everyone who commented, bit of a wild goose chase.

Jamie, to make the input values be taken literally, you need to either leave the type value of your x-axis unset or change it to type: 'literal'.
Here's a basic fiddle I created with your data to show how it can be interpreted exactly as input (vs. converted to dates): http://jsfiddle.net/brightmatrix/vtLswcex/1/
$(function () {
Highcharts.setOptions({
lang: {
thousandsSep: ',' // adds comma for axis labels
}
});
Highcharts.chart('container', {
xAxis: {
labels: {
formatter: function() {
return Highcharts.numberFormat(this.value,0);
}
}
},
series: [{
name: "Percentage",
data: [
[1472515200000, 49],
[1472601600000, 48.83],
[1472688000000, 49.6],
[1472774400000, 48.77]
]
}]
});
});
Note that I've added formatting for the x-axis labels, as well as a thousands separator in the Highcharts.setOptions() function, so that your labels will be more easily readable as trillions.
Does this help answer your question? If you are instead looking for a better way to format time-specific data, the comment by #morganfree is well worth looking into.

Related

Plotting data on x axis in Highstock

I am currently trying to plot some data which I receive via a HTTP request. The issue that I am having is that the x-axis doesn't plot the timestamp correctly because it it's in Unix format. I've read some other similar question on SO such as: Example One
The issue is that I'm not passing an object but directly an Unix time data. When hovering the graph, you can see that the x-axis doesn't display the date and hour correctly.
Here is a fiddle with my current graph: Graph Fiddle
Since you actually have datetime values, showing them using category is sort of a hack, and would also not show gaps between points correctly if they are not evenly spaced.
Instead you could merge your two arrays into pairs and then supply it to the series as proper X-Y values for a datetime axis. You also have to multiply your datetime values by 1000 to get milliseconds, which Highcharts expects.
For example (JSFiddle), merging:
dataArray.push(selectedData);
timeDataArray.push(selectedTime);
var mergedArray = timeDataArray.map(function(e, i) {
return [e*1000, dataArray[i]];
});
And axis and series:
xAxis: {
type: 'datetime'
},
series: [{
name: 'AAPL',
data: mergedArray
}]

Highcharts with dynamic yaxis labels as strings

I've been trying to add some custom yAxis labels to highcharts but I've not been able to so far. I've tried using formatter from a predefined array of strings and I've tried addAxis method but that doesn't get me the results I'm looking for.
Basically I have some numbers (lets say 4 and 4000) and I want to have these as my yLabels. However, I do NOT want the giant space between them. They need to be one right after the other and in ascending order. I cannot figure out how to do this leaving them as integers and I cannot figure out how to dynamically add them to highcharts as strings. I'm not even sure if this is possible
Any help would be greatly appreciated.
Here is the Y-axis label formatter documentation from Highcharts you're probably looking for. I wrote this fiddle to simulate the custom y-axis functionality you were wanting, although I'm not sure how you want to map those values to the x-axis data. This should give you a good starting point.
Code for reference:
$('#container').highcharts({
yAxis: {
categories: ['4', '4000', 'Foobar'],
labels: {
formatter: function () {
return this.value;
}
}
},
series: [{
data: [0, 1, 2]
}]
});
This stackoverflow question may also help although I noticed some dead links.

Highcharts - Stacked column data series

Im working with stacked column using Highcharts.
The data series im constructing is similar to this
series: [{
name: 'Apples',
data: [['2014-01-01',5], ['2014-01-02',3], ['2014-01-04',2], ['2014-01-05',7], ['2014-01-06',8]]
}, {
name: 'Oranges',
data: [['2014-01-01',3], ['2014-01-02',7], ['2014-01-04',9], ['2014-01-05',11], ['2014-01-06',19]]
}, {
name: 'Grapes',
data: [['2014-01-01',15], ['2014-01-02',23], ['2014-01-03',12], ['2014-01-05',17], ['2014-01-06',18]]
}]
http://jsfiddle.net/emgq47px/
If you take a closer look at the data, im missing 2014-01-04 data for Apples but instead the data is stacked on 2014-01-03.
One way of solving this would be to prepopulate categories and follow the same order for inserting my y values but that wont be a good way to solve as i may deal with large data sets down the line.
Any tips to head in the right direction is greatly appreciated.
UPDATE:
I'm populating my x and y co-ordinates with values from database. Database gives me date in (YYYY-mm-dd) format. So i'm converting that string to epoch time using strtotime function in PHP strtotime($res[0])
But then when I populate draw the highchart, i see wrong dates. I checked with online available epoch converters and it looks like conversion is right but i still cant figure out whats wrong here.
Even the x axis ticks seems to be slightly off.
Many thanks for your suggestions.
http://jsfiddle.net/emgq47px/3/
RESOLVED:
I had to multiply epoch time with 1000. This works.
Original answer: HighCharts - timeseries chart - irregular datetime interval on xAxis
Probably the best way is to use a datetime axis. This allows highcharts to know the data contains dates, and it can sort out the axis properly.
xAxis: {
lineWidth: 2,
type: 'datetime'
},
Once you do this, you need to supply valid date times in your data like this:
data: [[Date.UTC(2014, 0, 1),5],
[Date.UTC(2014, 0, 2),3],
[Date.UTC(2014, 0, 4),2],
[Date.UTC(2014, 0, 5),7],
[Date.UTC(2014, 0, 6),8]]
Note, months go from 0 to 11, not 1 to 12, so zero is January.
http://jsfiddle.net/0ofLx86d/
The problem is that you are marking x-axis type is category
xAxis: {
lineWidth: 2,
type: 'category'
},
So when you assign data data: [['2014-01-01',5], ['2014-01-02',3], like this to it then the first value is considered as category so when you assign ['2014-01-03',12] as last then it replaces previous one ['2014-01-04',12]. You can test it by keeping first two as 03 and last one as 04, then it will take 04 and not show 03.
Solution
Replace
type: 'category' to 'datetime'
and date to epoch time
data: [[1388534400000,5], [1388620800000,3], [1388793600000,2], [1388880000000,7]]
You can use custom function for label if you want to display date on x-axis in different format or use Date.UTC
Demo

Highcharts read text file

I'm new to JavaScript and HighCharts. I'm sure this is a very simple question, but I got lost.
I want to create a scatter chart with three lines. I need to read data from a text file, and the file looks like this:
x y1 y2 y3
1.02 1.00 6.70 8.19
2.04 1.00 13.30 8.19
3.06 1.00 13.50 8.19
4.08 1.00 9.60 8.19
5.10 1.00 14.60 8.19
6.12 1.00 19.20 8.57
So I need to plot three line with (x and y1), (x and y2), (x and y3)
And this is my HighCharts code:
<script type="text/javascript">
$(document).ready(function() {
var chart1 = new Highcharts.Chart(options);
});
var options = {
chart: {
renderTo: 'container',
type: 'scatter',
zoomType: 'xy'
},
title: {
text: 'Demo'
},
xAxis: {
title: {
enabled: true,
text: 'Time, ns'
},
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
text: 'Value'
}
},
series: []
};
$.get('///plot.txt', function(data) {
var lines = data.toString().split('\n');
$.each(lines, function(lineNo, line) {
var item = line.split()});
options.series[0].data[0].push(parseFloat(item[0]));
options.series[0].data[1].push(parseFloat(item[1]));
options.series[1].data[0].push(parseFloat(item[0]));
options.series[1].data[1].push(parseFloat(item[2]));
options.series[2].data[0].push(parseFloat(item[0]));
options.series[2].data[1].push(parseFloat(item[3]));
}, 'text')
var chart1 = new Highcharts.Chart(options);
</script>
I feel I messed up the entire code. I'm sorry but I never wrote JavaScript before. Any help would be hugely appreciated. Thank you in advance.
that's what you want to get : http://jsfiddle.net/z28vy/
Now a few comments
Read doc
You have to look at the HighChart documentation that is quite good, with live example on jsfiddle. Some are quite close to your use case (displaying data from data got with an AJAX call.)
What's peculiar in your need is to get raw text data, which force you into annoying parsing stuff.
Understand what you are doing
Even if your code could end up working, it looks like you are messing a bit with the sync/async story of your javascript. If you are a beginer that's a lot of things to learn at once. Not to mention you are trying to stick to jQuery style with anonymous functions...
Indent !
First thing, I do not know if it is just your post on here, or if you actually write code like that, but indent it properly ! It will show you a lot of problems at a glance. Especially when you are writing enclosed code (for example the success callback function of your ajax call.)
Arrays
Then, just a bit of logic : you have to know that although dynamic, arrays in javascript cannot have random access (read or write) on any non assigned slot. So when you are doing
options.series[0].data[0].push(parseFloat(item[0]));
you should have previously set options.series[0] which you didn't since your options object defines series as an empty array:
series: []
You can do that at the time of your ajax success method, or statically at options definition, depending on the flexibility you need in the number of series accross your use. I prefer you stay simple at first and do :
series: [{
name: 'Serie 1',
data: []
},{
name: 'Serie 2',
data: []
},{
name: 'Serie 3',
data: []
}]
Like that you can access each of your 3 series like you did... well except that you have the same problem with data[0] which does not exist neither for the same reason. Anyway do not bother much because...
First use your API as it goes
The way you add points to your series is far too complex anyway. series has an addPoint() method, just use it ! So instead of
options.series[0].data[0].push(parseFloat(item[0]));
options.series[0].data[1].push(parseFloat(item[1]));
Just do
options.series[0].addPoint([parseFloat(item[0]), parseFloat(item[1])]);
it's already easier to read :)
jQuery is not magical, it is just logical
Now the problem you have is your use of jquery $.each() I do not know if you just did not understand it or if you started to use it, then decided to hard-write your data handling to move on.
$.each(lines, function(lineNo, line) {
var item = line.split()});
options.series[0].data[0].push(parseFloat(item[0]));
options.series[0].data[1].push(parseFloat(item[1]));
As you will clearly see if you start indenting and separate things, you do nothing more than splitting each line for no purpose there.
Just use what you get with your split. If we say we are putting the current serie number in serieIdx :
$.each(lines, function(lineNo, line) {
var item = line.split(' ');
if(item.length==4 && !isNaN(parseFloat(item[0]))) { // skip unwanted line such as header or empty line
chart1.series[serieIdx].addPoint([parseFloat(item[0]), parseFloat(item[serieIdx+1])], false);
}
});
That's it. You just to have to iterate through your 3 series and you are good to go.
A side note about addPoint of serie in HighCharts
Be careful that if you call addPoint with invalid data (such as an array of anything instead of numbers) there is no visible error raised, but it breaks something anyway. In my case, before I added the test
if(item.length==4...
And since I had also at first a '\n' at the end of the last line, the upper split gave me one last empty string, which obviously ended up as en empty items array after the inner split. Which triggered an addPoint([NaN, NaN]) that purely made the lines between dots disappear for the whole graph. Be careful to that !
About the jsfiddle sample
jsfiddle obviously does not allow AJAX get but provide a trick instead : POST data in a json that jsfiddle server will resend back in the answer after the given delay (in my example I put 3 seconds.)
http://jsfiddle.net/z28vy/
I haven't read previous answer, since is pretty long, however I always advice to read tutorial from Highcharts: http://www.highcharts.com/docs/working-with-data/preprocessing-data-from-a-file-csv-xml-json

Highcharts datetime axis, how to disable time part (show only dates)?

My chart is displaying data day-by-day (user and system sent SMS/Newsletters). So time part is not relevant and unnecessary. Here is an example: http://jsfiddle.net/uaxZP/1/ where time "12:00" is displayed.
How can I force Highcharts to never display the time part in a "datetime" axis?
EDIT: Highcharts will display dates w/wo times based on chart or screen size. I've updated jsfiddle removing some data and now it's displaying also time parts.
You can intercept the x-axis label function and change it's output. In my example, I've changed it to render short dates:
http://jsfiddle.net/uaxZP/3/
{ xAxis:
labels: {
formatter: function() {
return Highcharts.dateFormat("%b %e", this.value);
}
}
}
The xAxis.labels.formatter property allows control over this. You also may notice I'm using Highcharts.dateFormat, which is a utility function for rendering dates. This is not mandatory, but it's a nice built in feature. Documentation on the xAxis formatter is here:
http://www.highcharts.com/ref/#xAxis-labels--formatter
The easiest way to do is using "minTickInterval"
xAxis: {
minTickInterval: 24 * 3600 * 1000
}
http://api.highcharts.com/highcharts#xAxis.minTickInterval

Categories