必要に迫られて perl でグラフを書くことになりました。 perl でグラフを書くためには以下のモジュールを利用すれば良いみたいです。
円グラフ: GD::Graph::pie
線グラフ: GD::Graph::lines
棒グラフ: GD::Graph::bars
棒と線の混ざったグラフ: GD::Graph::mixed
などを利用するとサクっとグラフが書けるし、ウェブで検索すると、そのためのサイトがちらほらとあるので非常に簡単にグラフが書けてよかったです。
しかし、GD::Graph の問題点もちらほら。
一個目
GD::Graph::mixed を利用したとき、グラフの右側が折れ線グラフの値のラベルで左側が棒グラフのラベルだとした場合、 y2_min_value の値が有効にならないみたいです。 y1_min_value の値と一緒になってしまうという、明らかにバグちっくな動作をしてしまう。利用している GD::Graph のバージョンの影響もあるのかな?
ちょっとサンプルコードを。
$graph->set(
:
types => [ qw(bars lines) ],
y1_max_value => 5,
y1_min_value => 0,
y2_max_value => 100,
y2_min_value => 70,
:
);
|
上記のようなコードにした場合、y1_min_value も y2_min_value も結局 “0” から始まってしまうので mixed グラフはあきらめて lines と bar のグラフを二個表示させるようにしました。orz
二個目
円グラフでグラフの中に文字を表示したい場合、その文字列が長いと悲しい状態になってしまいますなぁ・・。
以下、サンプルのグラフ。
でもって、これを回避するために GD::Text::Align など GD::Text 系を利用して色々編集できるらしいのですが、ウェブで探してもサンプルコードや、実際に表示できる成果物のグラフが無いので利用するのを断念しました。
php でグラフを書く場合には絵グラフの横に各フィールドの説明分を表示できるみたいなんですが perl ではそれができないみたいです。
表示しようとする文字列に “\n” を入れると改行はしてくれますが、センタリングしてほしいなぁ。とか、均等割付けしてほしいなぁ。と思う場合にはどうすんべな。とか思うのですが、それもあきらめました。
なので、 HTML で以下のように表示するようにしました。
これは簡単にできたのでコードを掲載してみます。
#!/usr/bin/perl
use strict;
use GD::Graph::pie;
use GD::Graph::colour qw( :files );
use GD::Text;
use Jcode;
GD::Graph::colour::read_rgb("./rgb.txt");
my @count = qw(4 5 3 2 5);
my @color = qw(OldLace OliveDrab OrangeRed PaleGoldenrod PaleTurquoise);
my @title = (
"1.長い文字列のデータ $count[0]",
"2.長い文字列のデータ $count[1]",
"3.長い文字列のデータ $count[2]",
"4.長い文字列のデータ $count[3]",
"5.長い文字列のデータ $count[4]",
);
#my @data = ([@title],[@count]);
my @data = ([@count],[@count]);
my $pie = GD::Graph::pie->new(190,200);
$pie->set(title => jcode("円グラフ")->utf8,
axislabelclr => 'black',
dclrs => [ @color ],
pie_height => 0,
start_angle => 180,
transparent => 0,
);
GD::Text->font_path("./");
$pie->set_title_font("ume-tgc4.ttf",8);
$pie->set_value_font("ume-tgc4.ttf",9);
my $image = $pie->plot(\@data);
my $graph = "./test_pie.png";
open( OUT,">$graph");
binmode OUT;
print OUT $image->png();
close OUT;
my $html = &make_title(\@title,\@count,\@color);
print "Content-type: text/html;charaset=utf-8\n\n";
print <<EOF;
<HTML>
<HEAD><META HTTP-EQUIV="Content-type" CONTENT="text/html;charset=utf-8"></HEAD>
<BODY>
<TABLE BORDER="0">
<TR><TD><IMG SRC="${graph}"></TD><TD>${html}</TD></TR>
</TABLE>
</BODY>
<html>
EOF
exit 1;
##
sub make_title {
my ($title,$count,$color) = @_;
my $c = 0;
my $html = "<table bgcolor=\"#DCDCDC\" border=0 class=\"sen\">\n";
foreach (@$title) {
$html .= "<tr bgcolor=\"#FFFFFF\" class=\"font\">\n";
$html .= "<td bgcolor=\"$color->[$c]\">$count->[$c]</td>\n";
$html .= "<td>$title->[$c]</td>\n</tr>\n";
$c++;
}
$html .= "</table>\n";
return ($html);
}
|
メインルーチンはグラフを書くのに一生懸命になっていて、サブルーチンの make_title() では TABLE タグを利用していてダサいですが、円グラフのフィールドに書くべき文字列を別途表示するようにしました。
既に組み立てた配列のデータをそのまま利用しているので比較的容易に情報を別途表示することが可能になりました。
詳細についてはコードをじっくりと追ってみてください;-)。あ。 make_title() の中ではスタイルシートとかバシバシ書くと更に見栄えが良くなると思います。
とまぁ、こんな感じで文字列が長い円グラフもなんとか見栄え良く表示できるようになりました。めでたしめでたし;-)。
ちなみに上記のコード中で利用している rgb.txt は emacs や netpbm に含まれているモノを利用できます。フォントは ume-tgc4.ttf を利用していますが、これは ume フォントに含まれているモノを利用しました。