Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

hbar or bar chart for my top 20 mail users with GD::Graph::hbars or GD::Graph::bars

by theravadamonk (Scribe)
on Aug 07, 2018 at 10:18 UTC ( #1219983=perlquestion: print w/replies, xml ) Need Help??
theravadamonk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I want to have a hbar or bar chart for my top 20 mail users with GD::Graph::hbars or GD::Graph::bars

My ultimate goal is to have a STACK bar chart since I have top 20 senders and recipients.

I have 2 files /tmp/senders.txt and /tmp/recipients.txt.

Let's first discuss one file. this time /tmp/senders.txt

DATA of /tmp/senders.txt

__DATA__ sender@domain1.com sender@domain2.com noreply@domain1.com noreply@domain1.com sender@domain1.com noreply@domain1.com

According to the above file ( Remember, This is just a sample file. Real file may contain about 1000 lines )

sender@domain1.com has 2 mails

sender@domain2.com has 1 mail

noreply@domain1.com has 3 mails

It reads it from start to end. when there are duplicates, It counts one by one.

This is the code for it

my $logfile = '/tmp/senders.txt'; open my $fh, '<', $logfile or die "Could not open $logfile : $!"; my %count=(); while (my $line = <$fh>) { foreach my $word (split /\s+/, $line) { ++$count{$word}; #print "$word\n"; #print "$count{$word}\n"; #print "<br />"; #print " \n"; } } for my $word ( (sort { $count{$b} <=> $count{$a} } keys %count) [0..1 +9] ) { #print "$word $count{$word}\n"; # THIS shows top 20 emails addres +s and its count. } close $fh;

Now What I need is to draw a hbar or bar chart with top 20 email addresses and their counts.

I have lost with below code? Could you pls correct me to go ahead.. ?

my @word = map{ $count{$_} || 0 } qw($word); my @count_word = map{ $count{$_} || 0 } qw($count{$word}); my $data = GD::Graph::Data->new([ [@word], [@count_word], ]) or die GD::Graph::Data->error;

Here's the full code

#!/usr/bin/perl use CGI ':standard'; use strict; use warnings; use GD::Graph; use GD::Graph::hbars; my $logfile = '/tmp/senders.txt'; open my $fh, '<', $logfile or die "Could not open $logfile : $!"; my %count=(); while (my $line = <$fh>) { foreach my $word (split /\s+/, $line) { ++$count{$word}; #print "$word\n"; #print "$count{$word}\n"; #print "<br />"; #print " \n"; } } for my $word ( (sort { $count{$b} <=> $count{$a} } keys %count) [0..1 +9] ) { #print "$word $count{$word}\n"; } close $fh; my @word = map{ $count{$_} || 0 } qw($word); #I think This is where I + have gone wring my @count_word = map{ $count{$_} || 0 } qw($count{$word}); # I think T +his is where I have gone wring my $data = GD::Graph::Data->new([ [@word], [@count_word], ]) or die GD::Graph::Data->error; my $graph = new GD::Graph::hbars(750,450); $graph->set( x_label => 'Email Users', x_label_position => 1/2, x_labels_vertical => 1, y_label => 'Count', title => 'Top Email Users', values_vertical => 0, show_values => 1, box_axis => 0 ); my $font = '/usr/share/fonts/gnu-freefont_freesans/FreeSans.ttf'; #my $font = '/usr/share/fonts/dejavu/DejaVuSans.ttf'; $graph->set_title_font($font,14); $graph->set_values_font($font, 8); $graph->set_x_axis_font($font,8); $graph->set_y_axis_font($font,8); $graph->set_legend_font($font,8); $graph->set_x_label_font($font,12); $graph->set_y_label_font($font,12); print header('image/png'); $graph->plot($data) or die $graph->error; binmode STDOUT; print $graph->gd->png;

Perl MONKS, Can correct my wrongdoing?

Replies are listed 'Best First'.
Re: hbar or bar chart for my top 20 mail users with GD::Graph::hbars or GD::Graph::bars
by hippo (Canon) on Aug 07, 2018 at 11:29 UTC
    my @word = map{ $count{$_} || 0 } qw($word); #I think This is where I + have gone wring my @count_word = map{ $count{$_} || 0 } qw($count{$word}); # I think T +his is where I have gone wring

    Yes, those lines don't make a great deal of sense. Perhaps you want something more like this?

    my @word = keys %count; my @count_word = map{ $count{$_} || 0 } @word;

      > Yes, those lines don't make a great deal of sense. Perhaps you want something more like this?

      my @word = keys %count; my @count_word = map{ $count{$_} || 0 } @word;

      Brilliant, Sir , Thanks a LOT. The above code works as expected. I Now need top 5 ( highest 5 ). So I changed the code in this way.. It works. It NOW shows top 5 as expected.

      my @word = ( (sort { $count{$b} <=> $count{$a} } keys %count) [0..4] ) +; my @count_word = map{ $count{$_} || 0 } @word;

      I have included below lines as well. I think I don't need below lines at all. I hv commented out them now

      Your IDEAS??

      #for my $word ( (sort { $count{$b} <=> $count{$a} } keys %count) [0.. +4] ) { # #print "$word $count{$word}\n"; #}

      The other thing I want to mention is that my ultimate goal is to have a STACK bar chart since I have another file /tmp/recipients.txt. This file is different from /tmp/senders.txt file.

      So, I think I can't achieve a STACK bar chart since I can't have a bar group like first highest sender and first highest recipient , 2 nd highest , 3 rd , 4th and 5 th highest sender and 5 th highest recipient

      I will have to pay attention to below lines

      my $data = GD::Graph::Data->new([ [@word], [@count_word], ]) or die GD::Graph::Data->error;

      If I can have a data structure in this way, I will be able to.

      my $data = GD::Graph::Data->new([ [@word], [@count_word], [@count_word_recip], ]) or die GD::Graph::Data->error;

      @word only contain senders, I can get @word_recip from /tmp/recipients.txt file with below code. I can include it to the same file

      my $logfile_recip = '/tmp/recipients.txt'; open my $fh, '<', $logfile_recip or die "Could not open $logfile_recip + : $!"; my %count_recip=(); while (my $line = <$fh>) { foreach my $word (split /\s+/, $line) { ++$count_recip{$word}; #print "$word\n"; #print "$count_recip{$word}\n"; #print "<br />"; #print " \n"; } } #for my $word ( (sort { $count_recip{$b} <=> $count_recip{$a} } keys +%count_recip) [0..4] ) { # #print "$word $count_recip{$word}\n"; #} close $fh; my @word_recip = ( (sort { $count_recip{$b} <=> $count_recip{$a} } key +s %count_recip) [0..4] ); my @count_word_recip = map{ $count_recip{$_} || 0 } @word_recip; #my $data = GD::Graph::Data->new([ # [@word_recip], # [@count_word_recip], #]) or die GD::Graph::Data->error;

      Hmm, Then, How can I have a BAR Group like first highest sender and first highest recipient , 2 nd highest , 3 rd , 4th and 5 th highest sender and 5 th highest recipient ?

      This may NOT work...
      my $data = GD::Graph::Data->new([ [@word @word_recip], [@count_word], [@count_word_recip], ]) or die GD::Graph::Data->error;

      Perl Monks are experts. Can I achieve a stack bar chart? I think I can't get a data structure for a stack bar chart in this way. anyway If I can't have it, I can go with 2 separate charts. Hope to hear from everyone

        I have included below lines as well. I think I don't need below lines at all. I hv commented out them now

        Yes, all the loop does is print. Since you have commented out the print line the loop becomes a no-op and may as well be removed entirely.

        my ultimate goal is to have a STACK bar chart since I have another file /tmp/recipients.txt.

        I'm not sure why you would want to stack unrelated senders and recipients. Regardless, I'll let someone who actually uses GD::Graph guide you on that one. Good luck.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1219983]
Approved by marto
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2018-10-17 22:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When I need money for a bigger acquisition, I usually ...














    Results (98 votes). Check out past polls.

    Notices?