Search code examples
perlgraphcharts

Plot bar chart with GD::Graph


I have data for each and every student, e.g.:

    Student Name         Score
    Jack                  89
    Jill                  70
    Sandy                 40

Now I'm trying to plot these in a bar chart using GD::Graph::Bar, but I see that I can manually declare all the X and Y values from the chart to be plotted.

Since I don't know the names and scores of each of the student (pulled from a text file), I want to be able to do the values automatically,

I was thinking hash keys and values was a good approach. I placed everything in a hash table: %hash(student name)=(score)

Can anyone help me plot this as a bar chart or guide me? Or would you recommend a different approach?

This is the part where I can plot the graph manually by entering the student names:

 my $graph = GD::Graph::bars->new(800, 800);

   @data = ( 
      ["Jack","Jill"],
      ['30','50'],
        );

     $graph->set( 
        x_label           => 'Students',
        y_label           => 'Scores',
        title             => 'Student Vs. Scores',
       y_max_value       => 60,
       y_tick_number     => 8,
       y_label_skip      => 2 
      ) or die $graph->error;

    my $gd = $graph->plot(\@data) or die $graph->error;

    open(IMG, '>file.png') or die $!;
     binmode IMG;
     print IMG $gd->png;

Solution

  • Assuming your data file is as follows, using tab delimiters.

    Student Name         Score
    Jack                  89
    Jill                  70
    Sandy                 40
    

    You could do something like this, pushing your x axis and y axis values from your data file to arrays.

    use strict;
    use warnings;
    use CGI qw( :standard );
    use GD::Graph::bars;
    
    open my $fh, '<', 'data.txt' or die $!;
    
    my (@x, @y);
    while (<$fh>) {
       next if $. == 1;            # skip header line
       push @x, (split /\t/)[0];   # push 'Student Names' into @x array
       push @y, (split /\t/)[1];   # push 'Score' into @y array
    }
    close $fh;
    
    my $graph = GD::Graph::bars->new(800, 800);
    
    $graph->set( 
                 x_label => 'Students',
                 y_label => 'Scores',
                 title   => 'Student Vs. Scores',
    ) or warn $graph->error;
    
    my @data = (\@x, \@y);
    $graph->plot(\@data) or die $graph->error();
    
    print header(-type=>'image/jpeg'), $graph->gd->jpeg;
    

    Giving you for example: enter image description here

    If you are wanting to use multiple y axis values, assuming you have another tab delimiter column with for example Score2, you could easily do something like this.

    my (@x, @y, @y2);
    while (<$fh>) {
       next if $. == 1;
       push @x, (split /\t/)[0];
       push @y, (split /\t/)[1];
       push @y2, (split /\t/)[2];
    }
    

    And change your @data array to:

    my @data = (\@x, \@y, \@y2);
    

    And your result would be: enter image description here