Как я могу преобразовать свои данные в координаты (x, y) для GD::Graph?

Я пишу программу, которая принимает входной файл от пользователя. В файле есть куча чисел, и я прочитаю числа в файле и создам график на основе этих чисел, используя GD::Graph.

Первая строка файла — ось X, вторая строка файла — значения Y, соответствующие оси X, а третья, четвертая, ... и т. д. Например:

1 2 3 4 5 
2 4 5 10 14
5 6 8 12 13

Таким образом, в приведенном выше примере первая строка — это ось x, вторая — значения y, соответствующие оси x, поэтому это даст 10 точек. (1, 2) (1, 5) (2, 4) (2, 6)....(4,10) (4,12) (5,14) (5, 13)

Я планирую прочитать каждую строку массива, а затем разбить строку на пробелы или вкладки и сохранить значения в массиве. Итак, массив 1 будет иметь ось X, массив 2 будет иметь ось Y, но как мне хранить 3-ю, 4-ю, 5-ю, ... и т. Д. Строки в массиве, чтобы они стали (x, y)?

Кроме того, как мне найти наибольшее значение для первой и второй строк (2 массива), чтобы я мог установить предел для своих осей X и Y?


person Community    schedule 03.04.2009    source источник


Ответы (3)


Упс, неправильно прочитал вопрос, вам нужен либо AoAoH, либо AoH, в зависимости от того, представляет ли каждая строка после первой линию или все это просто точки, которые должны быть нанесены соответственно. Вот как я бы это написал, если бы каждая строка в файле стала линией на графике:

#!/usr/bin/perl

use strict;
use warnings;
use List::Util qw/min max/;

my @x_points         = split " ", scalar <>; #read in the x axis labels
my ($x_min, $x_max)  = (sort { $a <=> $b } @x_points)[0,-1];
my ($y_min, $y_max)  = (0, 0);

#lines is an AoAoH, first layer are the lines to be drawn
#second layer is a list of coords
#third layer are the x and y coords
my @lines;
while (<>) {
    my @y_points = split;
    #if the two arrays are not the same size, we have a problem
    die "invalid file\n" unless @y_points == @x_points;

    $y_min = max($y_min, @y_points);
    $y_max = min($y_max, @y_points);

    push @lines, [ 
        map { { x => $x_points[$_], y => $y_points[$_] } }  
    0 .. $#x_points 
    ];
}

use Data::Dumper;

print "x min and max $x_min $x_max\n",
      "y min and max $y_min $y_max\n",
      "data:\n",
      Dumper(\@lines);

my $i;
for my $line (@lines) {
    $i++;
    print "line $i is made up of points: ",
        (map { "($_->{x}, $_->{y}) " } @$line), "\n";
}

И вот как бы я справился с этим, если бы это были просто точки для построения:

#!/usr/bin/perl

use strict;
use warnings;
use List::Util qw/min max/;

my @x_points         = split " ", scalar <>; #read in the x axis labels
my ($x_min, $x_max)  = (sort { $a <=> $b } @x_points)[0,-1];
my ($y_min, $y_max)  = (0, 0);

#lines is an AoAoH, first layer are the lines to be drawn
#second layer is a list of coords
#third layer are the x and y coords
my @points;
while (<>) {
    my @y_points = split;
    #if the two arrays are not the same size, we have a problem
    die "invalid file\n" unless @y_points == @x_points;

    $y_min = max($y_min, @y_points);
    $y_max = min($y_max, @y_points);

    push @points,
        map { { x => $x_points[$_], y => $y_points[$_] } }
        0 .. $#x_points;
}

use Data::Dumper;

print "x min and max $x_min $x_max\n",
      "y min and max $y_min $y_max\n",
      "data:\n",
      Dumper(\@points);

print "Here are the points: ", 
    (map { "($_->{x}, $_->{y}) " } @points), "\n";
person Chas. Owens    schedule 03.04.2009
comment
Я новичок в Perl, поэтому мне нужны некоторые пояснения по некоторым вопросам: если вы говорите, что первый и последний элементы будут выбросами, то предполагаете ли вы, что данные, введенные пользователем, отсортированы?? будет ли AoA содержать все данные, кроме осей x и y?? - person ; 03.04.2009
comment
Метки осей x и y должны быть отсортированы (иначе они не являются осями), AoA содержит только точки для построения. - person Chas. Owens; 03.04.2009
comment
@scotty- Вот несколько полезных руководств: Поваренная книга по структурам данных perldoc.perl.org/perldsc.html, учебник по массивам массивов perldoc.perl.org/perllol.html и справочник Учебное пособие perldoc.perl.org/perlreftut.html. - person daotoad; 03.04.2009
comment
@scotty- Кроме того, документация Perl поначалу немного громоздка (столько всего нужно прочитать), я нашел эту статью о PerlMonks очень полезной: perlmonks.org/?node=How%20to%20RTFM - person daotoad; 03.04.2009

Не совсем ответ на ваш вопрос, но не пропустите GD::Graph: :Данные.

Если вы уверены, что первое и последнее в каждой строке наименьшее/наибольшее, вам нужно будет использовать что-то вроде List::Util min() и max().


Я действительно не понимаю, что вы подразумеваете под «Первая строка файла — ось X, вторая строка файла — ось Y, а третья, четвертая и т. д. — соответствующие точки оси X».

person Anon    schedule 03.04.2009
comment
I mnt: первый набор из десяти значений будет значениями x для графика. Они будут равномерно распределены, например. 0, 1, 2, 3, ..., 9 Вторым набором из десяти значений будут значения y, соответствующие первым 10 значениям x, например. 20, 31, 42, 5, 7, ... Этот пример дает точки (0,20), (1,31), (2,42) и т. д. - person ; 03.04.2009
comment
я понимаю, что вы имели в виду ... это вводило в заблуждение, я отредактировал вопрос сейчас - person ; 03.04.2009

Вы можете увеличивать свои массивы x и y по мере продвижения.

#!/usr/bin/perl

use Data::Dumper;
use warnings;
use strict;

my @xs = ();
my @ys = ();
my $expecting_xs = 1;
my $last_xs_count;

while(<>) {
  chomp;
  my @values = split(/\s+/);
  if($expecting_xs) {
    push(@xs, @values);
    $last_xs_count = @values;
    $expecting_xs = 0;
  } else {
    if(@values != $last_xs_count) {
      die "Count mismatch";
    } 
    push(@ys, @values);
    $expecting_xs = 1;
  }
}

if(!$expecting_xs) {
  die("Odd number of lines");
}

my($xmin, $xmax) = extremes(@xs);
my($ymin, $ymax) = extremes(@ys);

print "xmin: $xmin xmax: $xmax ymin: $ymin ymax: $ymax\n";
print Dumper(\@xs), Dumper(\@ys);

sub extremes {
  my(@values) = @_;
  return undef unless @values;
  my $min = shift(@values);
  my $max = $min;
  for my $value (@values) {
    $max = $value if $value > $max;
    $min = $value if $value < $min;
  }
  return $min, $max;
}
person Andru Luvisi    schedule 03.04.2009