【问题标题】:Using Perl, how can I create charts using values in a CSV file?使用 Perl,如何使用 CSV 文件中的值创建图表?
【发布时间】:2009-08-28 00:21:56
【问题描述】:

我是新手,需要有关如何执行此任务的线索。我有一个包含以下示例数据的 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 文件中的值创建图表。

谁能给我推荐一些代码?

【问题讨论】:

    标签: perl perl-module


    【解决方案1】:

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

    CSVScatter

    【讨论】:

      【解决方案2】:

      给你,一些代码开始:

      #!/usr/bin/perl -w
      use strict;
      
      use Text::CSV;
      use GD;
      use Getopt::Long;
      

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

      【讨论】:

      【解决方案3】:

      好的,仅供娱乐

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

      输出:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 你能否更简单地解释一下(所以我破解了我的 Cartesian.pm 副本(如果你想这样做,请搜索 iconsize)。)。谢谢。
        • @Virus 安装GD::Graph::Cartesian 后,找到模块(在我的系统上它位于perl/site/lib/GD/Graph/Cartesian.pm)并搜索iconsize。您会看到默认大小为 7。您可以更改默认值,以便更改其他值。更好的办法是修改initialize() 方法以允许在调用new() 时指定不同的大小。
        • 谢谢 FM,你能不能也解释一下这个代码 "$xy_points[++ $i{$xy}][$xy eq 'X' ? 0 : 1] = $hr->{ $date};"
        • @Virus @xy_points 数组是要绘制的点列表,每个点存储一个数组引用:[X, Y](第一个点的 X 坐标将存储在 $xy_points[0][0]$xy_points[0][1] 中的 Y 坐标)。如果您仍然遇到问题,请使用 Perl 的调试器逐步执行代码。此外,您可以使用Data::Dumper 模块打印出@xy_points 数据结构。如果您不了解如何在 Perl 中处理复杂的数据结构,请看这里:perldoc.perl.org/index-tutorials.html(尤其是 perlreftutperldscperllol)。
        猜你喜欢
        • 2010-11-29
        • 2014-08-30
        • 1970-01-01
        • 2023-03-16
        • 2011-06-26
        • 1970-01-01
        • 1970-01-01
        • 2011-01-06
        相关资源
        最近更新 更多