Search code examples
chart.jsreact-chartjs

ChartJS vertical bar chart - measure percentage of the data in each column based on a specified max


I hope my title is well enough formulated, i am very new to chartJS actually just started i read the entire documentation multiple times and have done many simple to medium difficulty examples.

I am trying to graph the results of a test by categories, for example a Math test includes the categories: Algebra, Calculus, Analysis, Geometry , Combinatorics. I am making a graph in which each bar/column is a category and the data is the amount of correct questions from this category, as my max for a bar/column i want to have the maximum amount of questions in a given category, so no matter what number i plug this number will always be my max so 100%, so if i have 10 questions for Algebra in the test and i answer 7/10 correctly i want to see the bar be at 70% since this is the amount of correct questions from this specific category, but if i have 4/10 in Calculus this specific bar/column should be at 40%.

I hope my explanation was clear enough, i have all the data i need to achieve this ready to go, i just do not know how to exactly execute this no matter how much i research.

Any help or pointing in the right direction would be greatly appreciated!


Solution

  • The solution heavily depends on the format of your base data. It could for example be defined as follows:

    const testResults = [
      { category: 'Algebra', totalQuestions: 10, correclyAnswered: 7 },
      { category: 'Calculus', totalQuestions: 12, correclyAnswered: 9 },
      { category: 'Analysis', totalQuestions: 8, correclyAnswered: 5 },
      { category: 'Geometry ', totalQuestions: 10, correclyAnswered: 10 },
      { category: 'Combinatorics ', totalQuestions: 9, correclyAnswered: 5 }
    ];
    

    In this case, the chart data could be generated in the following way:

    const data = {
      labels: testResults.map(o => o.category),
      datasets: [
        {
          label: 'Test Results',
          backgroundColor: 'rgba(0, 255, 0, 0.2)',
          borderColor: 'rgba(0, 255, 0)',
          borderWidth: 1,
          data: testResults.map(o => (100 / o.totalQuestions * o.correclyAnswered))
        }
      ]
    };
    

    Then you would also have to define chart options to make sure tooltips and labels are properly formatted and the x-axis spreads full with between 0 and 100 %.

    const options = {      
      tooltips: {
        callbacks: {
          label: (tooltipItem, data) => {
            var label = data.datasets[tooltipItem.datasetIndex].label || '';
            return label + ': ' + tooltipItem.xLabel.toFixed(0) + '%';
          }
        }
      },
      scales: {
        xAxes: [{
          ticks: {
            min: 0,
            max: 100,
            stepSize: 10,
            callback: value => value + '%'
          } 
        }]
      }
    }
    

    The chart itself would be defined as follows:

    <HorizontalBar 
      data = { data } 
      options = { options } 
    />
    

    Please have a look at this StackBlitz.