Chartjs-Chart js draw line chart by points instead of by lines

1👍

1) I guess this is an easy way to separate each element and return an array

let mydata = [ 
              { 'a': 10, 'b': 5, 'c': 15},
              { 'a': 12, 'b': 3, 'c': 15},
              { 'a': 14, 'b': 6, 'c': 15},
              { 'a': 8, 'b': 2, 'c': 15}
             ];
                    
function split_(index){
  let a = [];
  mydata.forEach(e => a.push(e[index]));
  return a;
}

console.log(split_('a'));
console.log(split_('b'));
console.log(split_('c'));

Then, just call the array like this:

{
   label: 'a',
   data: split_('a'),
},
{
   label: 'b',
   data: split_('b'),
},
{
   label: 'c',
   data: split_('c'),
}

2) A more complex way that return an object you can directly append to the chart

let mydata = [
              { 'a': 10, 'b': 5, 'c': 15},
              { 'a': 12, 'b': 3, 'c': 15},
              { 'a': 14, 'b': 6, 'c': 15},
              { 'a': 8, 'b': 2, 'c': 15}
             ];
                    
function transform_(){
  let obj = [];
  Object.keys(mydata[0]).forEach(function t(key) {
      let a = [];
      mydata.forEach(e => a.push(e[key]));
      obj.push({ 
          label: key,
          data: a 
      });
  });
  return obj;
}

console.log(transform_());

EDIT : this second answer would only work for rectangular objects like the one you put in your example. If the object has different lenght in each index, it wouldn´t work. example:

  • This would work

               [
                { 'a': 10, 'b': 5, 'c': 15},
                { 'a': 12, 'b': 3, 'c': 15},
                { 'a': 14, 'b': 6, 'c': 15},
                { 'a': 8, 'b': 2, 'c': 15}
               ];
    
  • This wouldn´t work (‘d’ element wouldn´t be append to the chart)

               [
                { 'a': 10, 'b': 5, 'c': 15},
                { 'a': 12, 'b': 3, 'c': 15, 'd': 4},    //notice this 'd' element
                { 'a': 14, 'b': 6, 'c': 15},
                { 'a': 8, 'b': 2, 'c': 15}
               ];
    

Good luck!

1👍

If you also provide the x values is your data object you can just pass your data array like it is to the data fields and specify per dataset which property chart.js should take to get the y value like so:

const data = [{
    x: 'Red',
    'a': 10,
    'b': 5,
    'c': 15
  },
  {
    x: 'Blue',
    'a': 12,
    'b': 3,
    'c': 15
  },
  {
    x: 'Yellow',
    'a': 14,
    'b': 6,
    'c': 15
  },
  {
    x: 'Green',
    'a': 8,
    'b': 2,
    'c': 15
  },
]

const options = {
  type: 'line',
  data: {
    datasets: [{
        label: 'a',
        data: data,
        parsing: {
          yAxisKey: 'a'
        },
        borderColor: 'green'
      },
      {
        label: 'b',
        data: data,
        parsing: {
          yAxisKey: 'b'
        },
        borderColor: 'blue'
      },
      {
        label: 'c',
        data: data,
        parsing: {
          yAxisKey: 'c'
        },
        borderColor: 'red'
      }
    ]
  },
  options: {
  }
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.0/chart.js"></script>
</body>

You can read more about chart.js’s data structures here: https://www.chartjs.org/docs/master/general/data-structures.html#data-structures

0👍

You may need to just transform your raw data into a compatible data structure as you have outlined.

You can reduce the data using a two-dimensional reducer. After you have your groups, map them as entries. This handles undefined key-value pairs or holes in the data. For example, if the second item did not have a b value then then the b group would have a null as index 1.

const safePush = (arr, value, index) => {
  if (arr == null) { arr = []; }
  arr[index] = value;
  return arr;
};

const transformData = (rawData) =>
  Object.entries(rawData.reduce((acc, item, index) =>
    Object.entries(item).reduce((acc1, [key, value]) =>
      ({ ...acc1, [key]: safePush(acc1[key], value, index) }), acc), {}))
    .map(([ label, data ]) => ({ label, data }));

const data = [ 
  { 'a': 10 , 'b': 5 , 'c': 15 },
  { 'a': 12 , 'b': 3 , 'c': 15 },
  { 'a': 14 , 'b': 6 , 'c': 15 },
  { 'a': 8  , 'b': 2 , 'c': 15 },
];

const transformed = transformData(data);

console.log(transformed);
.as-console-wrapper { top: 0; max-height: 100% !important; }

0👍

Yes, definitively you have to group your data with something like this:

var data = [
    { 'a': 10, 'b': 5, 'c': 15},
    { 'a': 12, 'b': 3, 'c': 15},
    { 'a': 14, 'b': 6, 'c': 15},
    { 'a': 8, 'b': 2, 'c': 15},
  ],
  result = data.reduce(function (r, each) {
    for (let key in each) {
      if (r[key]) {
        r[key].push(each[key])
      } else {
        r[key] = [each[key]]
      }
    }

    return r;
  }, {});


console.log(result);

Then you can follow the directives here

Leave a comment