Почему Perl GD :: Graph жалуется на «Неверный набор данных»? - PullRequest
2 голосов
/ 06 апреля 2009

Я пишу небольшую программу на Perl для своего задания, и я новичок в Perl.

Код, который я написал, предоставляет мне те же значения, которые мне нужны, но я получаю эту ошибку при создании гистограммы.

Invalid data set: 0 at line 67

Строка 67 помечена комментарием в коде ниже.

Значения, хранящиеся по оси x:

40 44 48 52 64 76 83 104 105 148 149 249 431 665 805 1420 1500 

И y_axis:

16 1  1 6 1 1 1 1 1 1 1 1 1 1 1 2 5 

Вот мой код:

use GD::Graph::bars;

open(CHECKBOOK,"c:\\Perl\\bin\\ip_packet_trace1.txt");

my $counter = -1;
my @sizearray = {};
while ($record = <CHECKBOOK>) {
    @array = split(/\t/,$record);
    $counter++;
    $sizearray[$counter] = $array[6];

}

$counter++;

my @array1 = sort {$a <=> $b} @sizearray;
print "$counter\n";
print "@array1\n";


my @freq = {0...0};

foreach $elem (@array1){

    my $s = $freq[$elem]+1;

    $freq[$elem] = $s;
}


my $size = @freq;
my @x_axis = {};
my @y_axis = {};

my $count2 = -1;


for($i = 1; $i < $size; $i++){

    my $elem = $freq[$i];

    if($elem  and $elem > 0  ){

        $count2++;

        $x_axis[$count2] =  $i;

        $y_axis[$count2] = $elem;
    }

}


print "@x_axis \n";
print "@y_axis \n";




my $mygraph = GD::Graph::bars->new(500, 300); # line 67

$mygraph->set(x_label     => 'Month',

y_label     => 'Number of Hits',

title       => 'Number of Hits in Each Month in 2002',

) or warn $mygraph->error;

my @data = {@x_axis,@y_axis};



my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

open(IMG, '>C:\\image\\file.gif') or die $!;

binmode IMG;

print IMG $myimage->gif;

close IMG;

Ответы [ 4 ]

3 голосов
/ 06 апреля 2009

Я думаю, что ваше назначение @data, вероятно, виноват.

my @data = {@x_axis,@y_axis};

Это создает массив с одним элементом. Этот один элемент - хеш. Документация GD :: Graph показывает, что вам нужен массив массивов. Здесь, как указано daotoad, Data :: Dumper пригодится. Попробуйте следующее:

use Data::Dumper;
my @x_axis = 1...100;
my @y_axis = "a"..."z";
my @data = {@x_axis,@y_axis};
warn Dumper(\@data);

Вы можете увидеть, как интерпретируются данные, и увидеть, что они не совпадают с примером GD :: Graph :

@data = ( 
    ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
    [    1,    2,    5,    6,    3,  1.5,    1,     3,     4],
    [ sort { $a <=> $b } (1, 2, 5, 6, 3, 1.5, 1, 3, 4) ]
  );
2 голосов
/ 06 апреля 2009

Пожалуйста use strict и use warnings. Многие неприятные вещи, которые вы делаете в этом коде, будут помечены для вас, если вы используете эти прагмы.

Вы также затрачиваете много усилий, чтобы добавить в конец своих массивов. Вы можете использовать push, чтобы сделать это, не зная индекса последнего элемента. Использование push, как это позволит вам немного упростить ваш код.

Используйте () для создания пустого массива (ну, в действительности, списка). Используйте [], чтобы сделать ссылку на массив. используйте {}, чтобы сделать ссылку на хеш. Вы использовали хэш-ссылки во многих местах.

Также лучше использовать лексические файловые дескрипторы вместо глобальных файловых дескрипторов. Использование глобальных дескрипторов файлов - это использование ненужных глобальных переменных, что вызывает проблемы. Также проверьте успешность ваших звонков на open.

open( my $fh, '<', 'path/to/file)
    or die "Unable to open data file - $!\n";

Когда вы работаете со структурами данных, Data :: Dumper - это полезный модуль для просмотра происходящего.

use Data::Dumper;

my $foo = {
  bar => [ 0..5],
  baz => { a..z },
};

my @qux = ( [qw/a b c d/], [0..5] );

print Dumper $foo;
print Dumper \@qux;

Кроме того, взгляните на perldsc и perlreftut, в них есть хорошие примеры работы со ссылками и вложенными структурами данных.

1 голос
/ 07 апреля 2009

K. Я проверил и изменил ваш код. Код ниже работает. Часть массива, о которой все упоминали, была важной, но не единственной вашей проблемой. В примере cpan был анонимный массив, поэтому вместо передачи массивов @data 2 вам просто нужно было передать 2 ссылки на @ data.

#!/usr/bin/perl
#
use GD::Graph::bars;

my $size = @freq;
my @x_axis = qw(40 44 48 52 64 76 83 104 105 148 149 249 431 665 805 1420 1500);
my @y_axis = qw(16 1  1 6 1 1 1 1 1 1 1 1 1 1 1 2 5);

my $mygraph = GD::Graph::bars->new(500, 300); # line 67
$mygraph->set(x_label     => 'Month',
            y_label     => 'Number of Hits',
            title       => 'Number of Hits in Each Month in 2002',
) or warn $mygraph->error;
my @data = (\@x_axis,\@y_axis); # the important part.
my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

open(IMG, '>helping_graph.gif') or die $!;
binmode IMG;
print IMG $myimage->gif;
close IMG;
1 голос
/ 06 апреля 2009

Я не совсем уверен, на что смотрю, но одна вещь бросается в глаза: вы инициализируете свои массивы как ссылки на хэш:

hektor ~ $ perl -e '@sizearray = {}; print @sizearray, "\n"'
HASH(0x8031c0)

Если все, что вам нужно, это пустой массив, вы можете просто сказать:

my @sizearray;

Если вы хотите прояснить, что он новый и пустой, вам нужны скобки; увидеть ниже. (Однако, как говорит Брэд в своем комментарии, это излишне. Вероятно, вам следует привыкнуть видеть и писать более простую версию.)

my @sizearray = ();

Массивы хранят упорядоченные списки, а списки идут в скобках. Подробнее см. perldoc perldata.

...