Chart::Gnuplotでグラフを生成してみようB!

本カレンダーの一エントリを担当させていただくにあたり,あわててgitとnimの勉強を始めたばかりの赤フレームなメガネの女性に惹かれるかもしれないissmと申します.他のエントリの方々と比べるとgeek度は皆無だったりしますが,この11日,おつきあいいだたければ幸いです.

目次

  • はじめに
  • Chart::Gnuplotの概要
  • 準備
  • 基本
  • 実践
  • おわりに

はじめに

Perlでグラフを生成するためのモジュールとしては,グラフィックライブラリGDを利用したGD::Graphとか,GoogleChart APIを利用したGoogle::Chartとかが挙げられますが,最近,ふとしたきっかけで,Chart::Gnuplotなるモジュールの存在を知り,実際に使ってみたところ,なかなかいい感じでした.

今回は,そのChart::Gnuplotについて簡単に紹介してみます.

Chart::Gnuplotの概要

グラフ描画系のツールのひとつにgnuplotというものがあります.

スクリーンショットを2点.

私の場合,大学在学時のレポートとか卒業研究とかが触れるきっかけでした.TeXで扱うためにEPS形式で出力したものがIllustratorでイジれるとを知って,何やら遊んでいた記憶くらいかありませんが...そんなことはどうでもいいですね><

さて,このgnuplot,数式による描画もデータファイル読み込みによる描画もできたり,ラベルとか目盛りとかをはじめ,グラフ描画に関する様々な設定を細かく行えたりと,便利で高機能です.

そんなgnuplotをPerlから操作するためのインタフェイスを提供してくれるのが,このChart::Gnuplotです.

出力フォーマット

Chart::Gnuplotは,描画したグラフの出力フォーマットとして,次のものをサポートしています.(出力先の拡張子によって自動で切り替えてくれるみたいですね.)

The supported image formats are:

    bmp  : Microsoft Windows bitmap
    epdf : Encapsulated Portable Document Format
    epi  : Encapsulated PostScript Interchange format
    eps  : Encapsulated PostScript
    gif  : Graphics Interchange Format
    jpg  : Joint Photographic Experts Group JFIF format
    pdf  : Portable Document Format
    png  : Portable Network Graphics
    ppm  : Portable Pixmap Format
    ps   : PostScript file
    psd  : Adobe Photoshop bitmap file
    xpm  : X Windows system pixmap

If the filename has no extension, postscipt will be used.

cite: http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#output

これだけサポートしてくれていれば,まず困らないのではないでしょうか.

グラフ描画

gnuplotでは,2次元だけでなく,3次元の描画も行えます.もちろん,Chart::Gnuplotからでも可能です.

しかし,ここでは簡単に2次元描画にしぼって行きたいと思います.(私が試したことがないので.)

準備

前置きが長くなりましたが,まずは準備から.

In order to use this module, gnuplot need to be installed. If image format other than PS, PDF and EPS is required to generate, the convert program of ImageMagick is also needed.

cite: http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#DESCRIPTION

ということなので,gnuplotとかImageMagickとかをインストールしておきます.(ImageMagickは,PostScript・PDF・EPS形式以外のときに必要になります.入れておいて損はないかと思います.)

% sudo port install gnuplot
% sudo port install ImageMagick +perl
% sudo cpan -i Chart::Gnuplot

※ プラットフォームによって適宜置き換えてください.

基本

基本的な使い方は,だいたい次のような流れになります.

  • 描画用データの準備
  • gnuplotオブジェクトの生成・設定
  • データセットオブジェクトの生成・設定
  • 描画・出力

コードにすると,こんな感じです.

use Chart::Gnuplot;

# データの準備
my $xdata = [...];
my $ydata = [...];

# gnuplotオブジェクトの生成・設定
my $chart = Chart::Gnuplot->new(
  output => $filename,
  %opts_chart,
);

# データセットオブジェクトの生成・設定
my $dataset = Chart::Gnuplot::DataSet->new(
  xdata => $xdata, # arrayref
  ydata => $ydata, # arrayref
  %opts_dataset,
);

# 描画・出力
$chart->plot2d($dataset);

ちなみに,複数のデータセットを一度に描画することもできます.

my $dataset2 = Chart::Gnuplot::DataSet->new(...);

$chart->plot2d($dataset, $dataset2);

実践

もうちょっと実践的にやってみましょう.

データファイル

次のデータは,とあるサーバの負荷平均(ロードアベレージ)を,1日間,約10秒間隔で記録したものの一部です.(uptimeコマンドの出力を利用しています.)

1259593206,0.27,0.18,0.26
1259593216,0.31,0.19,0.27
1259593226,0.26,0.18,0.26
1259593236,0.22,0.17,0.26
1259593246,0.18,0.17,0.26
1259593256,0.16,0.16,0.25
1259593266,0.21,0.17,0.26
1259593276,0.18,0.17,0.25
1259593286,0.15,0.16,0.25
1259593296,0.13,0.15,0.25
...
1259679501,0.69,0.85,0.95
1259679511,1.20,0.96,0.98
1259679521,1.16,0.96,0.98
1259679531,1.38,1.01,0.99
1259679541,1.24,0.99,0.99
1259679551,1.12,0.97,0.98
1259679561,0.95,0.94,0.97
1259679571,0.80,0.91,0.96
1259679581,1.14,0.98,0.98
1259679591,0.97,0.95,0.97

このファイル名を,uptime.datとでもしておきます.

データの読み込み

データファイルにおける,コンマで区切った1列目(時刻)の系列を横軸,2列目(1分間の負荷平均値)の系列を縦軸としたグラフを生成することを考えてみます.

ということで,必要な部分を読み込みます.

my $t = [];  # 1列目のデータ系列が入る
my $y = [];  # 2列目のデータ系列が入る

open my $fh, '<', 'uptime.dat'  or  die $!;
while (my $row = <$fh>) {
  #chomp $row;
  my ($time, $load) = split /,/, $row;

  # 時刻データを,00:00:00からの秒数に置き換える
  my ($ss, $mm, $hh) = (localtime $time)[0..2];
  $time = ($hh*60*60 + $mm*60 + $ss);
  $time /= 60*60;  # 1時間を0〜1の範囲に圧縮する

  push @$t, $time;
  push @$y, $load;
}
close $fh;

gnuplotオブジェクトの準備

次にgnuplotオブジェクトを生成します.

#use Chart::Gnuplot; しているものとします

my $chart = Chart::Gnuplot->new(
  output    => 'uptime.png',
  imagesize => '1.5, 1.0',
  title     => '2009-12-01',
  xrange    => [0, 24],
  yrange    => [0, 3],
  xlabel    => 'time',
  ylabel    => 'load',
  grid => {
    width => 2,
    color => '#666666',
  },
  xtics => {
    along    => 1,
  },
  ytics => {
    along    => .5,
    labelfmt => '%.1f',
  },
  orient => 'landscape',
);

ここでのオプションの概要は次のような感じです.

output
出力先
imagesize
出力の相対的なサイズ
xrange
横軸の値の範囲
yrange
縦軸の値の範囲
xlabel
横軸につけるラベル
ylabel
縦軸につけるラベル
grid
補助線の種類とか色とか
xtics
横軸の刻み
ytics
縦軸の刻み
orient
用紙(?)の方向

gnuplotを使われたことのある方にとっては馴染みのある単語が並んでいますね.

詳細はCPANの同モジュールのページをご覧ください

データセットオブジェクトの準備

先に準備したデータを基に,データセットオブジェクトを生成します.

my $dataset = Chart::Gnuplot::DataSet->new(
  xdata => $t,
  ydata => $y,
  style => 'impulses',
  color => '#ff0000',
);

ここでのオプションの概要は次のような感じです.

xdata
横軸のデータ
ydata
縦軸のデータ
style
描画の種類
color
描画の色

描画の種類によって指定する項目が異なったりします.詳細は次をご覧ください.

描画・出力

あとは,次の1行で出力するだけです.

$chart->plot2d($dataset);

できあがり

すると,次のようなPNG画像ができあがります.

おわりに

以上,Chart::Gnuplotの概要と,同モジュールを使ってグラフを生成する過程をざっと紹介してみました.

それでは,楽しいグラフ描画ライフをおすごしください.

さーて,明日のカジュアルさんは?

冒頭で少し言及したGoogle::Chartモジュールの作者でもあるlestrratさんです.お楽しみに!