kristjan reinhold
kristjan reinhold

Reputation: 2048

ChartJS: Mapping Non numeric Y and X

I'm trying to map non numeric y and x and for some reason it does not work.

E.g.

xLabels: ["January", "February", "March", "April", "May", "June", "July"],
yLabels: ['Request Added', 'Request Viewed', 'Request Accepted', 'Request Solved', 'Solving Confirmed'],

And when i try to change:

data: ['Request Added', 'Request Viewed']

with

data: [{x: "January", y: 'Request Added'}, ...] 

Graph does not show a thing

Also i tried to use scales.yAxis.ticks.callback to modify and map against an array but that didnt work out either.

[0: 'Request Added', 1: 'Request Viewed']

EDIT: Essentially I need something like this

Request Added           x           x
Request Viewed                 x
Request Accepted               x    x
                    January, Feb, March

Basically a copy of this: https://answers.splunk.com/answers/85938/scatter-plot-with-non-numeric-y-values.html

Which also suggests to map against an array, but the callback in Y-ticks makes no freaking sense.. ? As i add labelY : [1,2,3,4,5,6] The Third argument of callback "values" is equal to [-2-1 0 1 2].

Upvotes: 3

Views: 6080

Answers (1)

jordanwillis
jordanwillis

Reputation: 10705

In order to use a category scale for both the X and Y axis, you must use the traditional data format of an array of values. Per the chart.js api docs...

Scatter line charts can be created by changing the X axis to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties

This implies that you can only use the data format {x: ' ', y: ' '} when at least the X axis is a linear scale (but I'm betting it only works if both the X and Y axis are linear).

Since you are limited to only using an array of values for your data, you must use at least 2 datasets in order to plot multiple values on the X axis (like what you are trying to do).

Here is a chart configuration that gives what you are looking for.

var ctx = document.getElementById("canvas").getContext("2d");
var myLine = new Chart(ctx, {
  type: 'line',
  data: {
    xLabels: ["January", "February", "March", "April", "May", "June", "July"],
    yLabels: ['Request Added', 'Request Viewed', 'Request Accepted', 'Request Solved', 'Solving Confirmed'],
    datasets: [{
      label: "My First dataset",
      data: ['Request Added', 'Request Viewed', 'Request Added'],
      fill: false,
      showLine: false,
      borderColor: chartColors.red,
      backgroundColor: chartColors.red
    }, {
      label: "My First dataset",
      data: [null, 'Request Accepted', 'Request Accepted'],
      fill: false,
      showLine: false,
      borderColor: chartColors.red,
      backgroundColor: chartColors.red
    }]
  },
  options: {
    responsive: true,
    title:{
      display: true,
      text: 'Chart.js - Non Numeric X and Y Axis'
    },
    legend: {
      display: false
    },
    scales: {
      xAxes: [{
        display: true,
        scaleLabel: {
          display: true,
          labelString: 'Month'
        }
      }],
      yAxes: [{
        type: 'category',
        position: 'left',
        display: true,
        scaleLabel: {
          display: true,
          labelString: 'Request State'
        },
        ticks: {
          reverse: true
        },
      }]
    }
  }
});

You can see what it looks like from this codepen.

If you are for whatever reason tied to using the {x: ' ', y: ' '} dataformat, then you will have to change both your scales to linear, map your data to numerical values, then use the ticks.callback property to map your numerical ticks back to string values.

Here is an example that demonstrates this approach.

var xMap = ["January", "February", "March", "April", "May", "June", "July"];
var yMap = ['Request Added', 'Request Viewed', 'Request Accepted', 'Request Solved', 'Solving Confirmed'];

var mapDataPoint = function(xValue, yValue) {
  return {
    x: xMap.indexOf(xValue),
    y: yMap.indexOf(yValue)
  };
};

var ctx2 = document.getElementById("canvas2").getContext("2d");
var myLine2 = new Chart(ctx2, {
  type: 'line',
  data: {
    datasets: [{
      label: "My First dataset",
      data: [
        mapDataPoint("January", "Request Added"),
        mapDataPoint("February", "Request Viewed"),
        mapDataPoint("February", "Request Accepted"),
        mapDataPoint("March", "Request Added"),
        mapDataPoint("March", "Request Accepted"),
      ],
      fill: false,
      showLine: false,
      borderColor: chartColors.red,
      backgroundColor: chartColors.red
    }]
  },
  options: {
    responsive: true,
    title: {
      display: true,
      text: 'Chart.js - Scatter Chart Mapping X and Y to Non Numeric'
    },
    legend: {
      display: false
    },
    scales: {
      xAxes: [{
        type: 'linear',
        position: 'bottom',
        scaleLabel: {
          display: true,
          labelString: 'Month'
        },
        ticks: {
          min: 0,
          max: xMap.length - 1,
          callback: function(value) {
            return xMap[value];
          },
        },
      }],
      yAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'Request State'
        },
        ticks: {
          reverse: true,
          min: 0,
          max: yMap.length - 1,
          callback: function(value) {
            return yMap[value];
          },
        },
      }]
    }
  }
});

You can see this in action at the same codepen.

Upvotes: 7

Related Questions