I have a chart where I have on the x-axis a datetime and on the y-axis a value in seconds, like 10, 200 or 4500. This works fine.
What I need is something like the behavior of the datetime, that when you have a date range it shows the days between that range, but if the range is really small, it displays the hours between that range. My request is that I would like to do the same but having a number in seconds, and if the range is huge, like maybe between 100 and 2500, it should be converted to minutes, what I have now is the following:
yAxis: {
title: {
text: 'Minutes',
margin: 10
},
min: 0,
tickInterval: 60,
labels:{
formatter: function(){
var minutes = ""
if (this.value > 59){
minutes = Highcharts.numberFormat((this.value/60), 0)
}
return minutes;
}
}
}
which is great for range between 60 and 500, but when the range is longer, it draws a lot of lines to display the minutes.
Any ideas? Can I change the tickInterval depending on some value?
I already have seen this reply Plotting seconds, minutes and hours on the yAxis with Highcharts, but I don't want to handle a datetime object on that axis.
I would really recommend using the inbuilt datetime axis type if you can. It takes away a lot of hassle with things like the issue you are asking about.
Failing that, you are on the right track in looking at the tickInterval. You could try not specifying a tickInterval at all, and let highcharts decide for you. It will usually find something sensible.
If that doesn't work well for you, then you will have to look at your data range and choose a sensible tickInterval yourself. One algorithm you could use is:
if (range < 500)
tickInterval = 60
else
tickInterval = 120
Obviously, if your range can go even bigger, you may need to have another case which switches the tickInterval to 300 or higher.
Related
I have a highcharts graph of speed(y axis) and time( x axis), each second posts a new speed, which means in an hour I will have 3600 data point, and that is a lot. I found out about tickInterval and the ability to shorten the amount of time drawn on the x axes, but as soon as I set it the ticks labels disappear and it shows only the first minute label
Here are two graph comparison of how it look like with tickInterval and without
without tickInterval:
With tickInterval:
I would have expected to see a tick label on x axis every minute but instead I see only this ? hmm ?
here is my code with less data points than I have:
http://jsfiddle.net/cyc89zop/1/
How can I fix this problem ?
2 things:
1) You have specified your axis type as "Time" which is not a valid option. What you want is datetime.
2) You have then specified categories for the x axis. categories and datetime axis types are mutually exclusive - you must use only one or the other, not both.
To get the proper dates with a datetime axis type, you specify either
1) an x value for each data point,in millisecond epoch time, or
2) a pointStart and pointInterval property for the series
http://api.highcharts.com/highcharts/plotOptions.series.pointStart
http://api.highcharts.com/highcharts/plotOptions.series.pointInterval
How can force nvd3 graph to have certain number of ticks to be displayed, for example, please find below the image of the graph plotted:
as seen below I have 7 values pushed to the array holding the 7 days of the week. However looks like they have more number of ticks than the actual values. What I'm looking for is something similar to this:http://nvd3.org/examples/line.html
However when i hover over these ticks they are misaligned as shown:
thats where the graph line should be and thats where the hovered tick shows the tooltip.but for some reason i dont get 7 ticks displayed instead gets 10 ticks displayed and all the hovered tooltips get misaligned.I also tried to force nvd3 to have specific # of ticks but didnt work.
chart2.xAxis
.ticks(7)
.tickFormat(function(d) {
return d3.time.format.utc('%b %d')(new Date(d));
});
here is the fiddle: http://jsfiddle.net/86hr7h1s/4/
I should ideally display 7 days and 7 ticks on the graph as oppose to duplicate days and 10 ticks on the graph.
Any ideas whats wrong and how to correct this?
EDIT::::::
I was able to fix my issue for 7 days with the below answer, using the tickValues() instead of ticks(). However, for large values, say display a graph data of 2 months, i'll have 30 data points. I still see that my graph ticks on hover dont align:
As you can see above the hover points still dont align with the vertical ticks. I dont want to force the ticksValues for more than 7 days on the graph.
Ay ideas how this could be achieved?
FYI:
I used this to make nvd3 display 7 values:
var datas = this.graphFunction(data);
chart2.xAxis.tickValues(datas[0].xAxisTickValues);
http://jsfiddle.net/86hr7h1s/5/
Thanks!
If you want to control the ticks precisely, you should use .tickValues() rather than ticks().
API Doc
I understand that the question was asked a long time ago, but I recently faced the same issue and found a good solution for it.
The reason of the issue with inaccurate ticks on the x-axis is the inaccurate internal numeric representation of dates that we want to display on the x-axis. As we can see here
https://nvd3.org/examples/line.html
when values on the x-axis are numbers, all ticks are displayed accurately. When we want to display dates on the x-axis, we also need to convert dates to some numeric representation. Typically dates are converted to the numeric representation via the Date.prototype.getTime() function and then labels are formatted using a code like this
chart.xAxis.tickFormat(d3.time.format('%b %Y')(date))
But the accuracy which the getTime() function provides to us is redundant in most cases. Assume we want to display only months and years on the x-axis and have a sorted list of dates where different items always have different moths but the item with a particular month may have any day and time. So, there may be a situation, where two adjacent list items have though have different months are very close to each other (for example, "Feb 28" and "Mar 1"). When we convert these list items to numeric representation using the getTime() function, the resulting list of big numbers remembers how far adjacent list items stand apart from each other. As the distance between adjacent chart points is always equal in NVD3 charts, NVD3 tries to fine-tune labels display to provide the info that some numbers are close to each other, but others are not. It leads to inaccurately displayed labels or even to duplicated labels if a chart has few points.
The solution is to omit redundant information about date and time when we convert dates to numbers. I needed to display only months and years on the x-axis and this code works great for me.
function getChartData(data) {
var values = data.map(function(val) {
return {
x: val.x.getUTCFullYear() * 12 + val.x.getUTCMonth(),
y: val.y
}
});
return [{
values: values,
key: 'date'
}];
}
function formatDate(numericValue) {
var year = Math.floor(numericValue / 12);
var month = numericValue % 12;
return shortMonthNames[month] + ' ' + year;
}
nv.addGraph(function() {
var data = [
...
{
x: new Date(2020, 2, 15, 15, 12),
y: 90
},
{
x: new Date(2020, 3, 3, 3, 54),
y: 50
},
...
];
var chart2 = nv.models.lineChart()
.showXAxis(true)
.showYAxis(true);
chart2.xAxis.tickFormat(formatDate);
d3.select('svg#svg')
.datum(getChartData(data))
.call(chart2);
return chart2;
});
Here we don't use the .tickValues() NVD3 function and so don't interfere to the default rendering engine, so the NVD3 lib can automatically add or remove axis labels when the viewport width is changed, and ticks and corresponding vertical lines are displayed exactly on the place where they should be.
Here is the full working example
http://jsfiddle.net/AlexLukin/0ra43td5/48/
I will try to explain better, starting with this image, that should make you understand better what i want to display in the graph. (the data will be taken from a database, but that's not important)
For every single day (and this graph represents a single day) I would like to see on the chart all the users (at most are 5-6) who have made at least one "action". These "actions" have a start time and an end time.
In this case, users are the series.And every series is a list of intervals (of time) of all actions made by the user on that day.
Example of series of a user who has made three actions on this day (yes, the time stamp will be multiplied by 1000)
[["1430362800","1430366400"],["1430391600","1430398800"],["1430424000","1430425800"]]
To view on the x-axis the interval 00:00 - 24:00 i will do
xAxis: {
type: 'datetime',
tickInterval: 3600 * 1000
}
Each horizontal line must be a user. To do that I should set the maximum and minimum of the y-axis. And , for example , if the users are 3 i'll do something like that (i will add only one axis, and the value (y) of each user must be 1,2,3...).
chart.addAxis({
min: 1,
max : 3,
ceiling:1,
tickInterval: 1,
labels: {
formatter: function() {
if (this.value <= 3){
return "";
}else{
return null;
}
}
}
});
The problem is that i don't know which type of chart used to display this type of data. Thanks
I have been facing this issue for a while and had found a fix too, but apparently this same issue has popped up again
So my visualization has a few drop downs and a chart (highcharts.js) which keeps changing dynamically depending on drop down selections
Xaxis - date and yaxis - Metric value and YOY value (column and line charts)
There is one dropdown namely "Daily" and "Hourly" which is in sync with my backend
For daily - data is for 14 days, and for hourly it's for 14*24 hours
So, with my codes used here, Xaxis comes correctly for the daily part showing 14 days(bars) there
But for Hourly, xaxis gets messed up and it counts each hour as a day and therefore shows me days for 14*24 like in the image below
So, I had already solved this problem by adding the following code in another tab :
xAxis: {
type : 'datetime',
min : Date.UTC(new Date(processed_json[0][0]).getYear(),new Date(processed_json[0][0]).getMonth(),new Date(processed_json[0][0]).getDate()),
max : Date.UTC(new Date(processed_json[processed_json.length - 1][0]).getYear(),new Date(processed_json[processed_json.length - 1][0]).getMonth(),new Date(processed_json[processed_json.length - 1][0]).getDate()),
dateTimeLabelFormats : {
second : '%H:%M',
minute : '%H:%M',
hour : '%H:%M',
day : '%e %b',
week : '%e',
month : '%b',
year : '%e'
},
plotOptions: {
series: {
pointStart: Date.UTC(new Date(processed_json[0][0]).getYear(),new Date(processed_json[0][0]).getMonth(),new Date(processed_json[0][0]).getDate()),
pointInterval : 3600 * 1000, // 3600*1000 for hourly
tickInterval : 3600 * 1000,
}
},
The "min","max" and "pointstart" take care that the graph comes like this as follows :
But, now I am using the same code in a new tab and getting Wrong graph again even after using - min, max and pointstart same as above.
I really am unable to understand this, if everything (processed_json, others etc) are exactly same, why am I getting this issue again?
Can someone suggest another method or tell me what I am doing wrong.
EDIT :
Also, I would like to add this functionality that when it zooms in the correct graph (2nd one), then it should show each hour in the xaxis. Is this feasible? If yes, how?
I have been using FLOT for many great things. Recently, i have needed to use it for time based plots. It worked perfect last month, but this month, i noticed that my last tick was smaller than the others. Also, i noticed that the tick label was not there.
Here is a JSFIDDLE of the issue for you to look at.
Due to the large amount of Javascript, i will keep all the code inside the Fiddle; unless the information is requested.
However, me and a friend thought of a simple workaround :
if(% 2 === 0) {
/*
Check if the data can be divided by 2
Repeat this for 3 as well (return the value and
plug it in the tickSize: [val, 'day'];
*/
}
The only drawback i see here if for months that have 31 days.
How would i fix this issue, or what did i do wrong that is causing this effect?
How about always making the chart 31 days wide (which means 30 days between first and last day and 15 ticks each 2 days wide)? You get that by setting the x axis maximum if your month does not have 31 days by itself:
xaxis: {
mode: "time",
timeformat: "%b %d",
tickSize: [2, 'day'],
max: 1398902400000
},
See this updated fiddle.