Wie kann ich mithilfe von Perl Diagramme mit Werten in einer CSV -Datei erstellen?
-
20-09-2019 - |
Frage
Ich bin neu dabei und brauche einen Ahnung, wie diese Aufgabe erledigt werden soll. Ich habe eine CSV -Datei mit folgenden Beispieldaten:
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....
Ich möchte ein Perl -Skript erstellen, um Daten aus der CSV -Datei (gemäß der angegebenen Benutzereingabe) zu lesen und XY -Diagramme (Scatter) zu erstellen. Nehmen wir an, ich möchte ein Diagramm für das Datum 2009-01-01 und Typ B erstellen. Der Benutzer sollte so etwas wie "2009-01-01 B" eingeben, und das Diagramm sollte mit den Werten aus der CSV-Datei erstellt werden.
Kann mir bitte jemand einen Code vorschlagen?
Lösung
Ich muss einige eigene Streudiagramme machen, also habe ich mit dem in den anderen Antworten vorgeschlagenen Modul herumgespielt. Für meinen Geschmack die Datenpunkte produziert von GD :: Graph :: kartesianisch sind viel zu groß und das Modul bietet keine Methoden zur Steuerung dieses Parameters, daher habe ich meine Kopie von gehackt Cartesian.pm
(suchen nach iconsize
Wenn Sie dasselbe tun möchten).
use strict;
use warnings;
use Text::CSV;
use GD::Graph::Cartesian;
# Parse CSV file and convert the data for the
# requested $type and $date into a list of [X,Y] pairs.
my ($csv_file, $type, $date) = @ARGV;
my @xy_points;
my %i = ( X => -1, Y => -1 );
open(my $csv_fh, '<', $csv_file) or die $!;
my $parser = Text::CSV->new();
$parser->column_names( $parser->getline($csv_fh) );
while ( defined( my $hr = $parser->getline_hr($csv_fh) ) ){
next unless $hr->{type} eq $type;
my $xy = $hr->{site};
$xy_points[++ $i{$xy}][$xy eq 'X' ? 0 : 1] = $hr->{$date};
}
# Make a graph.
my $graph = GD::Graph::Cartesian->new(
width => 400, # Image size (in pixels, not X-Y coordinates).
height => 400,
borderx => 20, # Margins (also pixels).
bordery => 20,
strings => [[ 20, 50, 'Graph title' ]],
lines => [
[ 0,0, 50,0 ], # Draw an X axis.
[ 0,0, 0,50], # Draw a Y axis.
],
points => \@xy_points, # The data.
);
open(my $png_file, '>', 'some_data.png') or die $!;
binmode $png_file;
print $png_file $graph->draw;
Andere Tipps
Hier gehen Sie, ein Code, mit dem Sie beginnen sollen:
#!/usr/bin/perl -w
use strict;
use Text::CSV;
use GD;
use Getopt::Long;
Anstelle von GD können Sie natürlich jedes Modul verwenden, das Sie möchten.
OK, Nur für Unterhaltungszwecke:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use List::AllUtils qw( each_array );
my $dbh = DBI->connect("DBI:CSV:f_dir=.", undef, undef, {
RaiseError => 1, AutoCommit => 1,
}
);
my $sth = $dbh->prepare(qq{
SELECT d20090101 FROM test.csv WHERE type = ? and site = ?
});
$sth->execute('B', 'X');
my @x = map { $_->[0] } @{ $sth->fetchall_arrayref };
$sth->execute('B', 'Y');
my @y = map { $_->[0] } @{ $sth->fetchall_arrayref };
my @xy;
my $ea = each_array(@x, @y);
while ( my @vals = $ea->() ) {
push @xy, \@vals;
}
my @canvas;
push @canvas, [ '|', (' ') x 40 ] for 1 .. 40;
push @canvas, [ '+', ('-') x 40 ];
for my $coord ( @xy ) {
warn "coords=@$coord\n";
my ($x, $y) = @$coord;
$canvas[40 - $y]->[$x + 1] = '*';
}
print join "\n", map { join '', @$_ } @canvas;
Hinzufügen von Achsen und im Allgemeinen verbessert in Streudiagramm - Ein wirklich enttäuschendes Modul - als Übung für den Leser.
Bitte beachten Sie, dass ich immer betrügen muss, wenn es um SQL geht. Ich würde mich für ein angemessenes Schaden freuen JOIN
das vermeidet das Bedürfnis nach @x
, @y
und each_array
.
Ausgabe:
| | | | * | | | | | | | | | | | | | | | | | * | | +----------------------------------------