...

View Full Version : Using Perl, how can I create charts using values in a CSV file?



vinodkaushik
08-28-2009, 11:41 AM
I am new to this and need a clue on how to do this task. I have a csv file with following sample data:

site,type,2009-01-01,2009-01-02,....
X,A,12,10,...
X,B,10,23,...
Y,A,20,33,...
Y,B,3,12,...

and so on....


I want to create a perl script to read data from the csv file (as per the given user input) and create XY(scatter) charts. Let's say that I want to create a chart for type B. The user should input something like "A" OR "B", and the chart should be created with the values from CSV file. Dates in X axis and Value numbers on Y axis with chart lines of values for each type A and B

I have searched for the modules in CPAN and I think below can help me but not sure how to start with.

#!/usr/bin/perl -w
use strict;

use Text::CSV;
use GD;
use Getopt::Long;

Can anyone please suggest me some code to start with?

Jolle
08-28-2009, 01:29 PM
To get your file, you can try following :



use Text::CSV
use IO::File

my @array;
my $fh = new IO::File($file_name,"r") or die "Couldn't open $file_name : $! \n";
my $csv = Text::CSV -> new();
$csv -> column_names ($csv -> getline($fh));
while ($csv ->getline_hr($fh)){
push (@array,$_);
}
This returns an array with hashrefs, that would allow you to do something like :


my @graph_array;
foreach (@array){
if (%{$_}{type} eq "B") {
push (@graph_array[0],%{$_}{"site"})
push ( @graph_array[1],%{$_}{"2009-01-01"})
}
}
* do something with the array to plot *

You need to construct an array of arrays if you want to use GD. Now depending on what you want to plot, you'll have to do something extra with it. Personally, I'm a bit baffled. You can't make an XY scatter plot with only one set of scalars. Please elaborate.

vinodkaushik
08-28-2009, 01:59 PM
Thanks for your comments. I have edited my question and hope this is clear now. Actually I want to create graphs between dates and values. The user should input "type" i.e. A or B.

Jolle
08-28-2009, 02:14 PM
Thanks for your comments. I have edited my question and hope this is clear now. Actually I want to create graphs between dates and values. The user should input "type" i.e. A or B.
Still, the problem remains. Should he do that for one site only, sum up the numbers for all sites, take the average,...

How to tackle the problem really depends on this. And actually, I wouldn't even go through the hassle of using csv. It's far easier to just load the file using the classic file handles, and construct a hash of arrays with keys "A","B","Date" and use the split() function to construct the arrays from the lines. From the data you have, I would even say to construct such a hash for every site, and combine them in a hash of hashes.

Then you get something like :


my %myfile;
while (<IN>){
chomp $_;
@line = split (",",$_);
my $site = shift @line;
my $label = shift @line;

$myfile{$site}{$label} = \@line;
}
If you have an array @dates with the dates (easily obtained from the first line), you can then construct an array of arrays for the GD functions :


my @grapharray = (\@dates,$myfile{$site}{$label})

vinodkaushik
09-01-2009, 11:52 AM
Hi,

I have created an array for dates as below.


open(my $csv_fh, '<', $csv_file) or die $!;

my $parser = Text::CSV->new();
my @dates = $parser->column_names( $parser->getline($csv_fh) );

my @dt = splice(@dates, 2);


but still need help to get values corresponding to given type. Please help.

Jolle
09-01-2009, 06:28 PM
Hi,

I have created an array for dates as below.


open(my $csv_fh, '<', $csv_file) or die $!;

my $parser = Text::CSV->new();
my @dates = $parser->column_names( $parser->getline($csv_fh) );

my @dt = splice(@dates, 2);


but still need help to get values corresponding to given type. Please help.
Please specify the question : you need them for each type over all sites, per site, want to average, sum, need all values,...

vinodkaushik
09-02-2009, 07:51 AM
I need the all values for each type per site.

vinodkaushik
09-03-2009, 10:07 AM
Just to update here. I found the solution using


use List::Util qw(sum)
my @sums = map { sum(@{$_}) } @array;
my $sum_of_sums = sum(@sums);
my @percentages = map { $_ / $sum_of_sums } @sums;



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum