Data-grouping for time-stamp series data is not correct when clicked on custom week button. How to customize it for week/ month, 3 month and 6 month grouping such that the average will be correct. Data for current and previous year is correct, problem is with Average Resolution Time and Average Response Time where data on tool-tip and y axis is in a format days:hours and hours:minutes respectively. That is time-stamp is being converted into days:hours and hours:minutes, but when it comes to calculate it's average, customization is needed for this to calculate correct average of time. How to customize it in a way such that it will be applied to Average Response time and average resolution time so that default calculations for current and previous year remains the same, which is working right now.
Most importantly how to customize the code to calculate average on time-stamp values. Here is the working fiddle: https://jsfiddle.net/aveohsdr/1/
var seriesOptions = [];
$(function() {
var html = '';
var groupingButtons = {
"Day": "day",
"Week": "week"
};
for (var i in groupingButtons) {
html += '<button class="btn btn-default dateWiseCriteria" data-criteria="' + groupingButtons[i] + '">' + i + '</button>';
}
$('.dateWiseCriteriaContainer').html(html);
var options = {};
$.extend(options, {
units: [
['day', [1]]
]
});
drawAnalyticalStockChart(getSeries(), options);
$(document).on('click', '.dateWiseCriteria', function() {
var options = {};
var criteria = $(this).data('criteria') == 'quater' ? 'month' : $(this).data('criteria');
criteria = $(this).data('criteria') == 'half' ? 'month' : criteria;
var value = $(this).data('criteria') == 'quater' ? 3 : 1;
value = $(this).data('criteria') == 'half' ? 6 : value;
$.extend(options, {
units: [
[criteria, [value]]
]
});
drawAnalyticalStockChart(getSeries(), options);
});
});
function drawAnalyticalStockChart(series, options) {
Highcharts.stockChart('container', {
chart: {
zoomType: 'x'
},
credits: {
enabled: false
},
rangeSelector: {
selected: 4
},
legend: {
enabled: true
},
scrollbar: {
showFull: false
},
xAxis: [{
crosshair: true,
}],
yAxis: [{ // Primary yAxis
type: 'datetime',
dateTimeLabelFormats: { //force all formats to be hour:minute:second
second: '%H:%M:%S',
minute: '%H:%M:%S',
hour: '%H:%M:%S',
day: '%H:%M:%S',
week: '%H:%M:%S',
month: '%H:%M:%S',
year: '%H:%M:%S'
},
labels: {
formatter: function() {
//get the timestamp
var time = this.value;
return _format_date(time, 1);
//now manipulate the timestamp as you wan using data functions
},
style: {
color: Highcharts.getOptions().colors[2]
},
x: 42
},
title: {
text: 'Average Resolution Time',
style: {
color: Highcharts.getOptions().colors[2]
},
margin: 53
},
opposite: true
}, { // Secondary yAxis
gridLineWidth: 0,
title: {
text: 'Cases',
style: {
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value} Cases',
style: {
color: Highcharts.getOptions().colors[0]
}
},
allowDecimals: false,
opposite: false
}, { // Tertiary yAxis
gridLineWidth: 0,
title: {
text: 'Average Response Time',
style: {
color: Highcharts.getOptions().colors[3]
}
},
labels: {
formatter: function() {
//get the timestamp
var time = this.value;
return _format_date(time, 0, 1);
//now manipulate the timestamp as you wan using data functions
},
style: {
color: Highcharts.getOptions().colors[3]
}
},
type: 'datetime',
dateTimeLabelFormats: { //force all formats to be hour:minute:second
second: '%H:%M:%S',
minute: '%H:%M:%S',
hour: '%H:%M:%S',
day: '%H:%M:%S',
week: '%H:%M:%S',
month: '%H:%M:%S',
year: '%H:%M:%S'
},
}],
tooltip: {
formatter: function() {
var points = this.points;
var groupingFormat = points[0].series.options.dataGrouping.dateTimeLabelFormats[points[0].series.currentDataGrouping.unitName][0];
var headerFormat = '<span style="font-size: 10px">' + Highcharts.dateFormat(groupingFormat, this.x) + '</span><br/>';
var pointFormat = '',
previousYear;
var isAllPointsHaveData = [];
points.forEach(function(point) {
if (point.y > 0) {
isAllPointsHaveData.push(1);
}
});
points.forEach(function(point) {
var name = point.series.name,
part;
var finalValue = point.y;
var showOnTooltip = true;
if (name === 'Current Year') {
previousYear = part = new Date(point.x).getFullYear();
} else if (name === 'Previous Year') {
part = new Date(point.x).getFullYear() - 1
} else if (name === 'Average Response Time') {
finalValue = _format_date(point.y, 0, 1, 1);
part = name + ' (' + previousYear + ')';
} else {
finalValue = _format_date(point.y, 1, 1);
part = name + ' (' + previousYear + ')';
}
if (!$.isEmptyObject(isAllPointsHaveData)) {
pointFormat += '<span style="color:' + point.color + '">\u25CF</span> <p style="color:' + point.color + '">' + part + '</p>: <b>' + finalValue + ' ' + point.series.tooltipOptions.valueSuffix + '</b><br/>';
}
});
return headerFormat + pointFormat;
},
},
plotOptions: {
series: {
showInNavigator: true,
dataGrouping: {
dateTimeLabelFormats: {
millisecond: ['%A, %b %e, %H:%M:%S.%L', '%A, %b %e, %H:%M:%S.%L', '-%H:%M:%S.%L'],
second: ['%A, %b %e, %H:%M:%S', '%A, %b %e, %H:%M:%S', '-%H:%M:%S'],
minute: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'],
hour: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'],
day: ['%A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'],
week: ['Week from %A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'],
month: ['%B %Y', '%B', '-%B %Y'],
year: ['%Y', '%Y', '-%Y']
},
enabled: true,
forced: true,
units: options.units,
smoothed: true,
}
}
},
series: getSeries()
});
}
function getSeries() {
seriesOptions = [{
name: 'Previous Year',
type: 'column',
yAxis: 1,
tooltip: {
valueSuffix: ' Case(s)',
},
data: [ /* Dec 2010 */
[
1480550400000,
0
],
[
1480636800000,
0
],
[
1480723200000,
0
],
[
1480809600000,
0
],
[
1480896000000,
0
],
[
1480982400000,
0
],
[
1481068800000,
0
],
[
1481155200000,
0
],
[
1481241600000,
0
],
[
1481328000000,
0
],
[
1481414400000,
0
],
[
1481500800000,
0
],
[
1481587200000,
0
],
[
1481673600000,
3
],
[
1481760000000,
0
],
[
1481846400000,
0
],
[
1481932800000,
0
],
[
1482019200000,
0
],
[
1482105600000,
0
],
[
1482192000000,
2
],
[
1482278400000,
0
],
[
1482364800000,
0
],
[
1482451200000,
0
],
[
1482537600000,
0
],
[
1482624000000,
0
],
[
1482710400000,
0
],
[
1482796800000,
0
],
[
1482883200000,
0
],
[
1482969600000,
0
],
[
1483056000000,
2
],
[
1483142400000,
0
]
],
"dataGrouping": {
"approximation": "sum"
},
"color": "#8085E9"
}, {
name: 'Current Year',
type: 'column',
yAxis: 1,
tooltip: {
valueSuffix: ' Case(s)',
},
data: [ /* Dec 2010 */
[
1480550400000,
0
],
[
1480636800000,
0
],
[
1480723200000,
0
],
[
1480809600000,
0
],
[
1480896000000,
0
],
[
1480982400000,
0
],
[
1481068800000,
0
],
[
1481155200000,
0
],
[
1481241600000,
0
],
[
1481328000000,
0
],
[
1481414400000,
0
],
[
1481500800000,
0
],
[
1481587200000,
0
],
[
1481673600000,
0
],
[
1481760000000,
0
],
[
1481846400000,
0
],
[
1481932800000,
0
],
[
1482019200000,
0
],
[
1482105600000,
1
],
[
1482192000000,
0
],
[
1482278400000,
0
],
[
1482364800000,
7
],
[
1482451200000,
0
],
[
1482537600000,
0
],
[
1482624000000,
0
],
[
1482710400000,
0
],
[
1482796800000,
0
],
[
1482883200000,
0
],
[
1482969600000,
0
],
[
1483056000000,
1
],
[
1483142400000,
0
]
],
"dataGrouping": {
"approximation": "sum"
},
"color": "#F45B5B"
}, {
name: 'Average Response Time',
type: 'spline',
yAxis: 2,
tooltip: {
valueSuffix: '',
},
data: [ /* Dec 2010 */
[
1480550400000,
0
],
[
1480636800000,
0
],
[
1480723200000,
0
],
[
1480809600000,
0
],
[
1480896000000,
0
],
[
1480982400000,
0
],
[
1481068800000,
0
],
[
1481155200000,
0
],
[
1481241600000,
0
],
[
1481328000000,
0
],
[
1481414400000,
0
],
[
1481500800000,
0
],
[
1481587200000,
0
],
[
1481673600000,
0
],
[
1481760000000,
0
],
[
1481846400000,
0
],
[
1481932800000,
0
],
[
1482019200000,
0
],
[
1482105600000,
2760
],
[
1482192000000,
0
],
[
1482278400000,
0
],
[
1482364800000,
1140
],
[
1482451200000,
0
],
[
1482537600000,
0
],
[
1482624000000,
0
],
[
1482710400000,
0
],
[
1482796800000,
0
],
[
1482883200000,
0
],
[
1482969600000,
0
],
[
1483056000000,
192060
],
[
1483142400000,
0
]
],
"dataGrouping": {
"approximation": "average"
},
"color": "#8BA6C7"
}, {
name: 'Average Resolution Time',
type: 'spline',
yAxis: 0,
tooltip: {
valueSuffix: '',
},
data: [ /* Dec 2010 */
[
1480550400000,
0
],
[
1480636800000,
0
],
[
1480723200000,
0
],
[
1480809600000,
0
],
[
1480896000000,
0
],
[
1480982400000,
0
],
[
1481068800000,
0
],
[
1481155200000,
0
],
[
1481241600000,
0
],
[
1481328000000,
0
],
[
1481414400000,
0
],
[
1481500800000,
0
],
[
1481587200000,
0
],
[
1481673600000,
0
],
[
1481760000000,
0
],
[
1481846400000,
0
],
[
1481932800000,
0
],
[
1482019200000,
0
],
[
1482105600000,
428400
],
[
1482192000000,
0
],
[
1482278400000,
0
],
[
1482364800000,
273600
],
[
1482451200000,
0
],
[
1482537600000,
0
],
[
1482624000000,
0
],
[
1482710400000,
0
],
[
1482796800000,
0
],
[
1482883200000,
0
],
[
1482969600000,
0
],
[
1483056000000,
360000
],
[
1483142400000,
0
]
],
"dataGrouping": {
"approximation": "average"
},
"color": "#8D4654"
}];
return seriesOptions;
}
function _format_date(ts, d = 0, h = 0, m = 0) {
var date_now = 0;
var label = '';
var date_future = ts * 1000;
// get total seconds between the times
var delta = Math.abs(date_future - date_now) / 1000;
// calculate (and subtract) whole days
var days = Math.floor(delta / 86400);
var finalValue = '';
if (d) {
label = days > 1 ? ' days ' : ' day ';
finalValue += days + label;
}
delta -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24;
if (h) {
if (d == 0) {
var totalHours = hours + (days * 24);
label = totalHours > 1 ? ' hours ' : ' hour ';
finalValue += totalHours + label;
} else {
label = hours > 1 ? ' hours ' : ' hour ';
finalValue += hours + label;
}
}
// calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60;
if (m) {
label = minutes > 1 ? ' minutes ' : ' minute ';
finalValue += minutes + label;
}
return finalValue;
}
I have resolved it by modifying approximation method like below, and it seems to work fine in all cases including zoom and scrolling.
var averageTime = this.options.data.slice(this.dataGroupInfo.start + this.cropStart, this.dataGroupInfo.start + this.cropStart + this.dataGroupInfo.length);
var currentYear = seriesOptions[1].data.slice(this.dataGroupInfo.start + this.cropStart, this.dataGroupInfo.start + this.cropStart + this.dataGroupInfo.length)
var len = arr.length;
var seconds = [], cases = [];
var finalArrayWithData = [];
for(var i in averageTime) {
if(averageTime[i][1] > 0) {
var date = _format_date(averageTime[i][1], 1, 1, 1, true);
seconds.push((((date.d * 24) * 60) * 60) + ((date.h * 60) * 60) + (date.m * 60));
cases.push(currentYear[i][1]);
finalArrayWithData['s'] = seconds;
finalArrayWithData['cases'] = cases;
}
}
var sumTopS = 0;
var sumBottom = 0;
for (var i in finalArrayWithData['cases']) {
if(finalArrayWithData['s'][i] > 0) {
sumTopS += finalArrayWithData['cases'][i] * finalArrayWithData['s'][i];
sumBottom += finalArrayWithData['cases'][i];
}
}
var averageS = 0;
if ($.isNumeric(sumTopS) && sumBottom) {
averageS = Math.round(sumTopS / sumBottom);
}
_dts = Date.UTC(1970, 0, 1, 0, 0, averageS) / 1000;
return _dts;
But I still believe there must be some direct way of doing it. I have to do trick to get data from various sources. They may be available from some other easily accessible variable.
来源:https://stackoverflow.com/questions/41542379/highstock-datagrouping-approximation-average-on-timestamp-values