Friday, November 22, 2019

Comparing two properties having different units - Generate line chart with two axes in C3 for multiple XY column pairs

  1. Final Code Solution
  2. Plot graph with many XY column pairs in C3 - Comparing many properties having the same unit
  3. Difficulties that you may face when feeding that function with values of variables

Final Code Solution

  This graph would have two axes having its own units, one in left representing values for the property 1 and another in the right representing values for the property 2. You can give custom names to the axes using the label attribute. The following code is to generate such a graph, but with hardcoded data. It has more possibility of raising errors but hard to identify them when modifying it for a dynamic value modification. I have listed a few such issues and solutions in the last of this chapter.


Code with hardcoded Data and Settings

const chart = c3.generate({
bindTo: '#chart',
  data: {
    xs: {
// corresponding columns of x of y columns (X axes for Ys’).
      'InputSetY1':'InputSetX1',
  'InputSetY2':'InputSetX2'
    },
    columns: [
      ['InputSetX1', 10, 20, 25, 30, 40],             // length of 5
      ['InputSetY1', 50, 20, 150, 110, 170],            // length of 5
      ['InputSetX2', 10, 15, 20, 25, 35, 40],         // length of 6
      ['InputSetY2', 120, 80, 260, 210, 220, 320]        // length of 6
    ],
    axes: {
      'InputSetY1':'y',
      'InputSetY2':'y2'
    }
  },
  axis: {
    x: {
      show: true,
      label: {
        text: 'Time (X Axis Tittle)',
        position: "outer-center"
      },
      multiline: true,
    },
y: {
  label: {
        text: 'Y Left Axis Name - InputSetY1',
        position: 'outer-middle'
  }
    },
y2: {
  show:true,
      label: {
        text: 'Y Right Axis Name - InputSetY2',
        position: 'outer-middle'
      }
    }
  }

});

Dynamic data and settings fed using variables

// Data to be provided
const y1Name = 'InputSetY1';
const y2Name = 'InputSetY2';

const y1Data = [120, 80, 260, 210, 220, 320]; // length of 5
const x1Data = [10, 20, 25, 30, 40];          // length of 5

const y2Data = [50, 20, 150, 110, 170];   // length of 6
const x2Data = [10, 15, 20, 25, 35, 40];      // length of 6

// Settings to fix the errors
const xs = {};
xs[y1Name]= 'x1';
xs[y2Name]= 'x2';

const axes = {};
axes[y1Name]= 'y';
axes[y2Name]= 'y2';

const chart = c3.generate({
bindTo: '#chart',
  data: {
    xs: xs,
    columns: [
      ['x1'].concat(x1Data),
      [y1Name].concat(y1Data),
      ['x2'].concat(x2Data),
      [y2Name].concat(y2Data)
    ],
    axes: axes
  },
  axis: {
    x: {
      show: true,
      label: {
        text: 'Time (X Axis Tittle)',
        position: "outer-center"
      },
      multiline: true,
    },
y: {
  label: {
        text: y1Name,
        position: 'outer-middle'
  }
    },
y2: {
  show:true,
      label: {
        text: y2Name,
        position: 'outer-middle'
      }
    }
  }
});

Note: You must not use dot notation when you are using with variables values as keys.

For Beginners

  Graphs are good to catch more information in one view rather than merely looking at unprocessed data. C3 graph is a popular JavaScript framework used to plot graphs from columns of data given. There are several examples given in the C3 official website. Though, there may be few varieties of our needs missing. This chapter is to discuss such a graph scenario where it is needed to compare two properties in one plane but it has two axes that represent values of the properties with their unit respectively. Also, we also discuss some difficulties arisen when changing its data dynamically.

Install C3 module

  I assume that your project is managed with NPM. Installing the C3 component is easy with NPM, just invoking following command in command prompt or terminal from the project’s directory. It will install the module, add it to the dependency file (package.json) and also include it to the app module (app.module.ts). 
  npm install c3  

  First, you need to import C3 into the script where you need to plot the graph. In angular, following snippet of code import all from the c3 module.
  import * as c3 from 'c3';  

Simple Line Chart Example

  You might have got to know basics functions used to plot graph in C3 script. “generate” function is used to plot the chart initially with given axes and data initially. The following script would generate a simple line chart for set hard-coded data provided. You may change inputs of its fields into variables to dynamically plot graphs with different data inputs. The “bindTo" attribute is used to plot the graph inside a particular HTML element specified by its id rather than creating one itself.
  const chart = c3.generate({
      data: {
          bindto: '#chart',
          x: 'x axis',
          columns: [
              ['x axis', 50, 40, 90, 220, 400, 290],
              ['InputSetY1', 40, 200, 100, 300, 450, 250],
              ['InputSetY2', 150, 310, 230, 330, 150, 440]
          ]
      }
  });

  The data set for both x-axes and y axes to plot the graph are feed to the field 'columns' as an array inside the 'data' object. The first values in the arrays inside the column array are used to determine which data series belongs to which axis. You can load the chart with another set of columns using the 'load' function dynamically. It can also be used with the time-related JavaScript inbuilt functions 'setInterval' or  'setTimeOut' which will expose viewers to an animation view.
  chart.load({                                                       
      columns: [                                                     
          ['InputSetY2', 90, 140, 90, 170, 70, 140]  
      ]                                                                     
  });                                                                      

The provided columns can also be unloaded with their ids.
  chart.unload({               
      ids: 'InputSetY1'        
  });                                  

Plot graph with many XY column pairs in C3 - Comparing many properties having the same unit


It is similar to our topic here but both y-axes are properties of the same unit. So, the chart would have only one Y-axis. Hence, you do not have to specify the data set for the y-axis.

Note: You must consider inverted commas (type) of both attributes and values and it may not work otherwise.

const chart = c3.generate({
bindTo: '#chart',
  data: {
    xs: {
// corresponding columns of x and y pairs (X-axes for Ys’).  y:x
'InputSetY1':'InputSetX1',
  'InputSetY2':'InputSetX2'
    },
    columns: [
      ['InputSetX1', 10, 20, 25, 30, 40],             // length of 5
      ['InputSetY1', 50, 20, 150, 110, 170],     // length of 5
      ['InputSetX2', 10, 15, 20, 25, 35, 40],         // length of 6
      ['InputSetY2', 120, 80, 260, 210, 220, 320] // length of 6
    ],
  },
  axis: {
    x: {
      show: true,
      label: {
        text: 'Time (X Axis Tittle)',
        position: "outer-center"
      },
      multiline: true,
    },
y: {
  label: {
        text: 'Y Left Axis Name - InputSetY1',
        position: 'outer-middle'
  }
    }
  }
});



Warning: It requires meaningful names for data columns of y-axes since they are indicated below the graphs with their line colors.
Example: we are using ‘InputSetY1’ and ‘InputSetY2’  here.

Difficulties that you may face when feeding that function with values of variables

Inside the general function, a variable should not be given as a string argument inside a nested object which is an argument to the generate function. The following kind of errors may arise and difficult to detect if do so.
  1. Values of the second Y-axis in the right are not given but in decimal range 0 to 1.
  2. Error: x is not defined for id = "InputSetY1".

Solution: Define an empty object, set the values for corresponding keys(variables) and use the object as argument inside the nesting object.
const Obj1= {};
Obj1[variable_name] = ‘xInputSet1’;
Obj1[variable_name] = ‘xInputSet2’;

Note: You must not use dot notation when you are using with variables values as keys.

1. Values of the second Y-axis in the right are not given but in decimal range 0 to 1.
    If the corresponding axis is not set for the data Y2, C3 will not plot the graph with appropriate values for the second y-axis. However, two charts will appear with two axes everything as expected except the second y-axis wrong range of values problem.
Solution:
const axes = {};
axes[InputSetY1]= 'y';
axes[InputSetY2]= 'y2';
2. Error: x is not defined for id = "InputSetY1".

  ERROR Error: x is not defined for id = "x1".               
      at c3.js:6902                                                               
      at Array.forEach (<anonymous>)                              
      at ChartInternal.convertDataToTargets (c3.js:6900) 
      at ChartInternal.initWithData (c3.js:1411)                
      at ChartInternal.init (c3.js:1271)                                
      at new Chart (c3.js:83)                                               
      at Object.generate (c3.js:1249)                                  
It might be link c3.js TypeError: b.value is undefined in Mozilla browsers.
Solution:
const xs = {};
xs[InputSetY1]= ' InputSetX1';
xs[InputSetY2]= ' InputSetX2';

Complete Code.: Given at the very beginning

Tags: two-axis line chart, C3 chart with two axes, multiple set of xy data set, C3 chart, Compare properties of two units C3 chart library, C3 JavaScript chart library,  generate c3 graph with dynamic values, generate c3 chart using variables inside, c3.js TypeError: b.value is undefined, c3.js Error: x is not defined for id.

No comments:

Post a Comment

Whats New

How redundant uploads can be avoided in social media apps?

People spend more time on social media, and it influences the most and changes to societies. They want to share photos and videos often when...

You may also like to read

x

emailSubscribe to our mailing list to get the updates to your email inbox...

Delivered by FeedBurner