使用 Perl,如何使用 CSV 文件中的值创建图表?

发布于 2024-08-03 22:34:39 字数 345 浏览 2 评论 0原文

我对此很陌生,需要有关如何完成这项任务的线索。我有一个包含以下示例数据的 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....

我想创建一个 perl 脚本来从 csv 文件读取数据(根据给定的用户输入)并创建 XY(散点)图表。假设我想为日期 2009-01-01 创建一个图表并输入 B。用户应输入类似“2009-01-01 B”的内容,并且应使用 CSV 文件中的值创建图表。

有人可以建议我一些代码来开始吗?

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 date 2009-01-01 and type B. The user should input something like "2009-01-01 B", and the chart should be created with the values from CSV file.

Can anyone please suggest me some code to start with?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

十六岁半 2024-08-10 22:34:39

不要从代码开始。从 CPAN 开始。

CSV分散

Don't start with code. Start with CPAN.

CSV and Scatter

半衾梦 2024-08-10 22:34:39

在这里,您可以从一些代码开始:

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

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

当然,您可以使用您想要的任何模块来代替 GD。

Here you go, some code to start with:

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

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

Instead of GD you can, of course, use whatever module you'd like.

挽你眉间 2024-08-10 22:34:39

好的,仅用于娱乐目的

#!/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;

添加坐标轴并在 ScatterPlot——一个真正令人失望的模块——留给读者作为练习。

请注意,当涉及到 SQL 时我总是不得不作弊。我希望有一个适当的 JOIN 来消除对 @x@yeach_array 的需要。

输出:

|
|
|
|            *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|          *
|
|
+----------------------------------------

OK, for entertainment purposes only:

#!/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;

Adding axes and generally improving in ScatterPlot — a truly disappointing module — left as an exercise to the reader.

Please note that I always have to cheat when it comes to SQL. I would appreciate a proper JOIN that obviates the need for @x, @y and each_array.

Output:

|
|
|
|            *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|          *
|
|
+----------------------------------------
樱娆 2024-08-10 22:34:39

我需要自己制作一些散点图,所以我尝试了其他答案中建议的模块。根据我的口味, 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;

I need to make some scatter plots of my own, so I played around with the module suggested in the other answers. For my taste, the data points produced by GD::Graph::Cartesian are far too large, and the module provides no methods to control this parameter, so I hacked my copy of Cartesian.pm (search for iconsize if you want to do the same).

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文