ZottoSL
ZottoSL

Reputation: 167

HighChart - Group data by day

I have a graph with 3 series and 4 points for each series. Each of these points corresponds to 4 different days (one point per day). That is to say that each day will have 3 points in total, since they are 3 series. But these 3 points differ in the hour, minutes and seconds.

What I want to do is keep this data in the X axis to show it in the Tooltip, but that the 3 points are aligned.

Let's show it with examples.

This is what I currently have:

    chart = new Highcharts.StockChart({

        chart: {
            renderTo: "container",
            type: 'spline'
        },

        colors: ['#3131F8', '#FB1C1C', '#008000', '#f7a35c', '#8085e9',
            '#f15c80', '#e4d354', '#8085e8', '#8d4653', '#91e8e1'],

        yAxis: {
            opposite: false,
            showLastLabel: true,
            labels: {
                enabled: true,
                align: "right"
            },

            title: {
                text: 'Tensión'
            }
        },

        rangeSelector: {
            enabled:  true
        },

        tooltip: {
            pointFormatter: function () {
                var n = this.series.name;
                var s = '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>';
                    return s + Highcharts.numberFormat((this.y / 1000), 2, '.') + ' kV</b><br/>';
            }
        },

        legend: {
            enabled: true
        },

        navigation: {
            buttonOptions: {
                enabled: true
            }
        },

        series: [{"name":"Minima","pointInterval":86400000,"data":[[1538467200000,215.9],[1538581500000,217.6],[1538651700000,218],[1538728200000,218.5]]},{"name":"Maxima","pointInterval":86400000,"data":[[1538506800000,228.8],[1538530200000,228.4],[1538676000000,229.3],[1538779500000,228.8]]},{"name":"Promedio","pointInterval":86400000,"data":[[1538438400000,223.9365],[1538524800000,224.0667],[1538611200000,224.4135],[1538697600000,224.45]]}]
    });

http://jsfiddle.net/ZottoSL/8vedjxLs/5/

This is what I want (I modified the X point in the data to achieve the visual effect, but actually I want to keep it):

    chart = new Highcharts.StockChart({

        chart: {
            renderTo: "container",
            type: 'spline'
        },

        colors: ['#3131F8', '#FB1C1C', '#008000', '#f7a35c', '#8085e9',
            '#f15c80', '#e4d354', '#8085e8', '#8d4653', '#91e8e1'],

        yAxis: {
            opposite: false,
            showLastLabel: true,
            labels: {
                enabled: true,
                align: "right"
            },

            title: {
                text: 'Tensión'
            }
        },

        rangeSelector: {
            enabled:  true
        },

        tooltip: {
            pointFormatter: function () {
                var n = this.series.name;
                var s = '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>';
                    return s + Highcharts.numberFormat((this.y / 1000), 2, '.') + ' kV</b><br/>';
            }
        },

        legend: {
            enabled: true
        },

        navigation: {
            buttonOptions: {
                enabled: true
            }
        },

        series: [{"name":"Minima","pointInterval":86400000,"data":[[1538438400000,215.9],[1538524800000,217.6],[1538611200000,218],[1538697600000,218.5]]},{"name":"Maxima","pointInterval":86400000,"data":[[1538438400000,228.8],[1538524800000,228.4],[1538611200000,229.3],[1538697600000,228.8]]},{"name":"Promedio","pointInterval":86400000,"data":[[1538438400000,223.9365],[1538524800000,224.0667],[1538611200000,224.4135],[1538697600000,224.45]]}]
    });

http://jsfiddle.net/ZottoSL/9bk8hq3n/1/

That is to say, that when drawing the graph on the X axis, only consider the year, month and day, discriminating the hour, minutes and seconds.

Thanks!

Upvotes: 2

Views: 4112

Answers (2)

ewolden
ewolden

Reputation: 5803

You can achieve the desired look by using dataGrouping. That way you don't have to do any extra processing. All you would need to do, is to give this definition:

plotOptions: {
  series: {
    dataGrouping: {
      forced: true,
      units: [
        ['day', [1]]
      ]
    }
  }
},

To get the actual time of the point in the tooltip you could then do this:

tooltip: {
  pointFormatter: function() {
    var n = this.series.name;
    var s = '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>';
    return Highcharts.dateFormat('%m/%d - %H:%M', this.series.xData[this.index]) + s + Highcharts.numberFormat((this.y / 1000), 2, '.') + ' kV</b><br/>';
  }
},

Where Highcharts.dateFormat('%m/%d - %H:%M', this.series.xData[this.index]) gets the actual time of the point.

Working JSFiddle Example: http://jsfiddle.net/ewolden/omfdy8nc/

API on dataGrouping: https://api.highcharts.com/highstock/series.line.dataGrouping


To remove the extra time that can be in front or after the series when dataGrouping is done per day we need to set a min and max value. The reason we have this whitespace is because the original data have values that are not exactly set at midnight per day.

Adding the following load event will find the minumum/maximum full day and set the xAxis and the navigator xAxis to these values:

chart: {
  events: {
    load: function() {
      let extremes = this.xAxis[0].getExtremes()
      let min = extremes.dataMin - extremes.dataMin % (1000 * 60 * 60 * 24),
        max = extremes.dataMax - extremes.dataMax % (1000 * 60 * 60 * 24);
      this.update({
        xAxis: {
          min: min,
          max: max
        },
        navigator: {
          xAxis: {
            min: min,
            max: max
          }
        }
      }, true, false, false)
    }
  }
},

Working example: http://jsfiddle.net/ewolden/omfdy8nc/32/

API on the load event: https://api.highcharts.com/highstock/chart.events.load

API on chart.update: https://api.highcharts.com/class-reference/Highcharts.Chart#update

Upvotes: 5

Wojciech Chmiel
Wojciech Chmiel

Reputation: 7372

You can use the same timestamp for each point on the same day as x property and save the real timestamp in the point object for example as realX. Then use real timestamp in tooltip.pointFormatter to create show the real date for each point. Check the example posted below.

HTML:

<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>

<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

JS:

var data = [{
    name: "Minima",
    pointInterval: 86400000,
    data: [
      [1538467200000, 215.9],
      [1538581500000, 217.6],
      [1538651700000, 218],
      [1538728200000, 218.5]
    ]
  }, {
    name: "Maxima",
    pointInterval: 86400000,
    data: [
      [1538506800000, 228.8],
      [1538530200000, 228.4],
      [1538676000000, 229.3],
      [1538779500000, 228.8]
    ]
  }, {
    name: "Promedio",
    pointInterval: 86400000,
    data: [
      [1538438400000, 223.9365],
      [1538524800000, 224.0667],
      [1538611200000, 224.4135],
      [1538697600000, 224.45]
    ]
  }],
  finalData = [],
  i,
  j,
  series,
  point;

for (i = 0; i < data.length; i++) {
  series = data[i];
  finalData[i] = {
    name: series.name,
    pointInterval: series.pointInterval,
    data: []
  };

  for (j = 0; j < series.data.length; j++) {
    point = series.data[j];

    finalData[i].data.push({
      x: data[0].data[j][0],
      y: point[1],
      realX: point[0]
    });
  }
}

chart = new Highcharts.StockChart({

  chart: {
    renderTo: "container",
    type: 'spline'
  },

  colors: ['#3131F8', '#FB1C1C', '#008000', '#f7a35c', '#8085e9',
    '#f15c80', '#e4d354', '#8085e8', '#8d4653', '#91e8e1'
  ],

  yAxis: {
    opposite: false,
    showLastLabel: true,
    labels: {
      enabled: true,
      align: "right"
    },

    title: {
      text: 'Tensión'
    }
  },

  rangeSelector: {
    enabled: true
  },

  tooltip: {
    pointFormatter: function() {
      var n = this.series.name,
        s = '<span style="color:' + this.series.color + '">' + n + '</span>: <b>',
        date = 'Date: ' + Highcharts.dateFormat('%e. %b %H:%M', this.realX),
        number = Highcharts.numberFormat((this.y / 1000), 2, '.') + ' kV</b><br/>';
      return s + number + date;
    }
  },

  legend: {
    enabled: true
  },

  navigation: {
    buttonOptions: {
      enabled: true
    }
  },

  series: finalData
});

Demo: https://jsfiddle.net/BlackLabel/qfv1yzmh/1/

Upvotes: 0

Related Questions