Perlを使用して、CSVファイルで値を使用してチャートを作成するにはどうすればよいですか?
-
20-09-2019 - |
質問
私はこれに慣れていないので、このタスクを行う方法についての手がかりが必要です。次のサンプルデータを備えたCSVファイルがあります。
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....
CSVファイル(指定されたユーザー入力に従って)からデータを読み取り、XY(spatter)チャートを作成するPERLスクリプトを作成します。日付2009-01-01とタイプBのチャートを作成したいとしましょう。ユーザーは「2009-01-01 B」のようなものを入力する必要があり、CSVファイルの値でチャートを作成する必要があります。
誰でも私に最初からコードを提案してもらえますか?
解決
私は自分の散布図を作る必要があるので、他の答えで提案されているモジュールをいじりました。私の好みのために、によって生成されたデータポイント gd :: graph :: cartesian 大きすぎて、モジュールはこのパラメーターを制御する方法を提供しないため、のコピーをハッキングしました Cartesian.pm
(検索する iconsize
同じことをしたい場合)。
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;
他のヒント
ここに行きます、いくつかのコードから始める:
#!/usr/bin/perl -w
use strict;
use Text::CSV;
use GD;
use Getopt::Long;
もちろん、GDの代わりに、必要なモジュールを使用できます。
わかった、 エンターテインメントのためだけに:
#!/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;
軸を追加し、一般的に改善します 散布図 - 本当に残念なモジュール - 読者への演習として残されました。
SQLに関しては、私は常にチートしなければならないことに注意してください。適切に感謝します JOIN
それは必要性を回します @x
, @y
と each_array
.
出力:
| | | | * | | | | | | | | | | | | | | | | | * | | +----------------------------------------
所属していません StackOverflow