[Chartjs]-Chart.js: different dataset size

11👍

What you are describing is actually possible with chart.js as long as at least 1 of your datasets can be expressed using the alternate scatter chart dataset. Let me walk you through an example where I show the daily avg as bars and the hourly avg as a line (aka, a mixed chart type).

First, configure a bar chart with labels for each day of the week and provide the daily average values for the data as your first dataset.

Next, create another dataset, but set it’s type property to 'line'. Since we are wanting to use a different X axis and a different set of labels, you must express your data using the {x: 0, y: 2} notation. This will allow you to circumvent the scale from using the labels defined above.

Finally, in your options.scales config, define 2 xAxes scales and associate your 2nd dataset to the 2nd X axis scale (also set it’s display property to false so you don’t see any of the 2nd scale).

You end up with a chart configuration that looks like this.

var ctx = document.getElementById("canvas").getContext("2d");
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
    datasets: [{
      type: 'bar',
      label: 'Daily Avg',
      backgroundColor: chartColors.red,
      data: dailyAvgData,
      borderColor: 'white',
      borderWidth: 2
    }, {
      type: 'line',
      label: 'Hourly Avg',
      borderColor: chartColors.green,
      backgroundColor: chartColors.green,
      borderWidth: 1,
      fill: false,
      pointRadius: 0,
      xAxisID: 'x-axis-2',
      data: hourlyAvgData
    }]
  },
  options: {
    responsive: true,
    title: {
      display: true,
      text: 'Chart.js - Combo Chart With Multiple Scales (X Axis)'
    },
    tooltips: {
      mode: 'nearest',
      intersect: true
    },
    scales: {
      xAxes: [{}, {
        id: 'x-axis-2',
        type: 'linear',
        position: 'bottom',
        display: false,
      }],
      yAxes: [{
        ticks: {
          min: 0,
          max: 50
        }
      }]
    }
  }
});

You can see it in action at this codepen.

Here is another example but instead of using a combo chart (daily is bars, hourly is line), both plots are lines. The approach is exactly the same except the chart type is changed from bar to line.

Note, in this version I have adjusted the daily avg line over by one so that the points are plotted at the “end of the day”. The previous example was showing the daily avg at the start of each day (which is technically not correct).

Here is an example codepen that demonstrates the line version of the chart.

0👍

Landing here after searching how to implement a moving average in Chart.js, I’ve struggled to fully understand the answer of @jordanwillis, so maybe this can be useful to someone else too.

The central idea is that you can assign a format of data (for each dataset in datasets) such that the y component represents the value of the series and the x – this is the crucial point IMHO – matches the label (in the unique, common labels array, that will be the shared x axis for all the series, i.e. the datasets) where you want to plot that specific point.

So my example for a moving average of N (say 7 day moving average) and a generic asymmetric shift of S between 0 and N-1 (e.g. 3) would be

var valuesMean7 = movingAverage(7, 3, ydata, xlabels);

where I have defined:

function movingAverage(N, shift, values, labels) {
    var NN = values.length;
    var valuesMean = [];
    rightShift = N - shift - 1;
    for (let i = shift; i < NN - rightShift; i++) {
        var mean = 0;
        for (let j = i - shift; j < i - shift + N; j++) {
            mean += values[j];
        }
        mean = mean / N;
        valuesMean.push({
            x: labels[i],
            y: mean
            });
    }
    return valuesMean;
}

Leave a comment