PHP-Scatterplot について
散布図作成ツールをPHPで作ってみました。
Githubで公開しています。 Composer でインストールできます。
こんな感じの基本的な散布図に1次回帰線を入れてみたり、
![](https://macocci7.net/blog/wp-content/uploads/2023/06/Matrix00.png)
こんな感じに複数のデータをレイヤーとして重ねたり、参照線や仕様限界線を入れてみたり、
凡例表示してみたり、色や線の太さを変えてみたり、色々カスタマイズできます。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/ChangingProperties.png)
こんな感じで1つのCSVの複数の項目について組み合わせを変えて比較したりできます。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/scatterplot_matrix.png)
環境要件
- PHP CLI 8.1以降
- Imagick PHP Extention
- Composer
インストール
作業用ディレクトリを作り、そこでコマンドを実行します。
composer require macocci7/php-scatterplot
![](https://macocci7.net/blog/wp-content/uploads/2023/06/scatterplot01.png)
基本的な使い方
パッケージに同梱されている examples をコピーしていじってみましょう。
cp -ra vendor/macocci7/php-scatterplot/examples ./
BasicUsage.php を見てみましょう。
<?php
require('../vendor/autoload.php');
use Macocci7\PhpScatterplot\Scatterplot;
$sp = new Scatterplot();
$layers = [
[
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [1,2,3,4,5,8,4,7,11,9,1],
],
];
$sp->layers($layers)
->create('img/BasicUsage.png');
これだけで散布図を作成することができます。
実行してみましょう。
php -f BasicUsage.php > BasicUsage.md
examples/img/BasicUsage.png という画像ファイルができています。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/BasicUsage.png)
こんな感じの基本的な散布図が保存されています。
複数のレイヤーを使う
複数の種類のデータをレイヤーとして重ねた散布図を作ることができます。
examples/UsingLayers.php を見てみましょう。
<?php
require('../vendor/autoload.php');
use Macocci7\PhpScatterplot\Scatterplot;
$sp = new Scatterplot();
$layers = [
'John' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [1,2,3,4,5,8,4,7,11,9,1],
],
'Jake' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [11,8,10,7,9,6,5,3,4,2,1],
],
'Hugo' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [4,8,10,1,9,6,5,3,7,1,11],
],
'Alex' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [3,5,11,4,8,2,9,10,1,11,7],
],
];
$legends = array_keys($layers);
$sp->layers($layers)
->create('img/UsingLayers.png');
複数の種類のデータを $layers にハッシュとして格納してから
$sp->layers($layers) としてデータセットし、 create() で1つの散布図を生成しています。
実行してみましょう。
php -f UsingLayers.php > UsingLayers.md
example/img/UsingLayers.png という画像が生成されています。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/UsingLayers.png)
プロパティの変更
上記2つの散布図は味気ないので、色々と属性を変更してみます。
examples/AdjustDisplayByMethods.php を開いてみましょう。
<?php
require('../vendor/autoload.php');
use Macocci7\PhpScatterplot\Scatterplot;
$sp = new Scatterplot();
$layers = [
'John' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [1,2,3,4,5,8,4,7,11,9,1],
],
'Jake' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [11,8,10,7,9,6,5,3,4,2,1],
],
'Hugo' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [4,8,10,1,9,6,5,3,7,1,11],
],
'Alex' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [3,5,11,4,8,2,9,10,1,11,7],
],
];
$legends = array_keys($layers);
$sp->layers($layers)
->limitX(0, 12) // Xの下限上限
->limitY(0, 12) // Yの下限上限
->gridXPitch(2) // Xのグリッド刻み幅
->gridYPitch(2) // Yのグリッド刻み幅
->bgcolor('#ccccff') // キャンバス背景色
->colors(['#ffffff']) // プロットの色
->plotSize(4) // プロット円の直径
->fontColor('#333333') // フォントの色
->grid(1, '#999999') // グリッドの線幅と色
->gridXOn() // X軸グリッド表示ON
->gridYOn() // Y軸グリッド表示ON
->regressionLine(3, ['#666666', '#cc2222', '#2222cc', '#22cc22']) // 1次回帰線:幅と色
->referenceLineX(1.5, 1, '#00ccff') // 参照線X:参照値、線幅、色
->referenceLineY(1.5, 1, '#00ccff') // 参照線Y:参照値、線幅、色
->specificationLimitX(0.5, 11.5, 1, '#ff00ff') // 仕様限界線:下限、上限、線幅、色
->specificationLimitY(0.5, 11.5, 1, '#ff00ff') // 仕様限界線:下限、上限、線幅、色
->labelX('DATA X') // X軸ラベル
->labelY('DATA Y') // Y軸ラベル
->caption('SCATTER PLOT') // キャプション
->legends($legends) // 凡例
->create('img/AdjustDisplayByMethods.png');
メソッドは他にもいくつかあります。
resize(), frame(), axis(), fontPath(), fontSize(),
gridXOn(), gridXOff(), gridYOn(), gridYOff(),
referenceLineXOff(), referenceLineYOff(), referenceLinesOff(),
specificationLimitXOff(), specificationLimitYOff(), specificationLimitsOff(),
regressionLineOn(), regressionLineOff(), legendOff() などです。
では、実行してみましょう。
php -f AdjustDisplayByMethods.php > AdjustDisplayByMethods.md
examples/img/AdjustDisplayByMethods.png が生成されています。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/ChangingProperties-1.png)
このような感じになります。
解析データの取得
画像生成をすることなく、解析データだけを取得できるようにクラスを切り出しています。
Macocci7\PhpScatterplot\Analyzer を使うと、
平均、最大値、最小値、分散、標準偏差、共分散、相関係数、1次回帰線式などの
解析結果のデータを取得することができます。
Macocci7\PhpScatterplot\Scatterplot クラス自体もこのクラスを継承しているので、
Scatterplot のインスタンスでも同様に取得可能です。
examples/ParsedData.php を開いてみましょう。
<?php
require('../vendor/autoload.php');
use Macocci7\PhpScatterplot\Analyzer;
$a = new Analyzer();
$layers = [
'John' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [1,2,3,4,5,8,4,7,11,9,1],
],
'Jake' => [
'x' => [1,2,3,4,5,6,7,8,9,10,11],
'y' => [11,8,10,7,9,6,5,3,4,2,1],
],
];
var_dump($a->parse($layers));
Macocci7\PhpScatterplot\Analyzer のインスタンスを生成して、
parse() メソッドの引数に $layers を渡すと、解析結果をハッシュで返します。
実行してみましょう。
php -f ParsedData.php > ParsedData.txt
実行結果の出力が ParsedData.txt に保存されています。
ちょっと長いので、データの構造を示します。
[
'John' => [ // $layers のキー
'count' => 11, // データ(x,y)の件数
'x' => [
'Mean' => 6, // Xの平均値
'Max' => 11, // Xの最大値
'Min' => 1, // Xの最小値
'Variance' => 10, // Xの分散
'StandardDeviation' => 3.1622776601683795, // Xの標準偏差
],
'y' => [ (構造はXと同じなので省略) ],
'Covariance' => 5.181818181818182, // XとYの共分散
'CorrelationCoefficient' => 0.5135343537364686, // 相関係数
'RegressionLineFormula' => [ // 1次回帰線の式: Y = aX + b
'a' => 0.5181818181818182, // 傾き
'b' => 1.8909090909090907, // Y切片
],
],
'Jake' => [ (構造は'John'と同じなので省略) ],
]
散布図マトリックス
例えば、1つのCSVの複数の項目について、それぞれのペアで散布図を作る
などといったことをすると、データの比較が楽にできます。
使用例としては、東京の1ヵ月間の気象データを基にマトリックスを作ってみました。
平均気温、最高気温、最低気温、降水量、日照時間、平均気圧などの項目が
気象庁のWEBサイトから一つのCSVでダウンロード可能です。
フォーマットにかなりクセがあり使いにくいデータですが、
必要なデータを簡単に取り出せるように CSV操作用のクラスを用意しています。
examples/Matrix.php を開いてみましょう。
<?php
require('../vendor/autoload.php');
require('./class/CsvUtil.php');
require('./class/Combination.php');
use Macocci7\CsvUtil;
use Macocci7\Combination;
use Macocci7\PhpScatterplot\Scatterplot;
$cu = new CsvUtil();
$cb = new Combination();
$cu->load('csv/weather_tokyo.csv')
->encode('SJIS', 'UTF-8')
->offset(7);
$heads = $cu->heads(4);
$days = $cu->raw()->column(0);
$dictionary = [
'平均気温(℃)' => 'Mean Temperature(℃)',
'最高気温(℃)' => 'Maximum Temperature(℃)',
'最低気温(℃)' => 'Minimum Temperature(℃)',
'日照時間(時間)' => 'Sunshine Hours(h)',
'降水量の合計(mm)' => 'Precipitation Amount(mm)',
'平均現地気圧(hPa)' => 'Mean Local Air Pressure(hPa)',
];
$columns = [1, 4, 7, 10, 14, 21];
$parsed = [];
$pairs = $cb->pairs($columns);
foreach ($pairs as $index => $pair) {
$x = $pair[0];
$y = $pair[1];
$layers = [
'Tokyo, Japan' => [
'x' => $cu->float()->column($x),
'y' => $cu->float()->column($y),
],
];
$sp = new Scatterplot();
$sp->layers($layers)
->regressionLineOn()
->labelX($dictionary[$heads[$x]])
->labelY($dictionary[$heads[$y]])
->caption('Weather in Tokyo : ' . $days[0] . '~' . $days[count($days) - 1])
->create(sprintf("img/Matrix%02d.png", $index));
$parsed[] = $sp->parse($layers);
}
examples/csv/weather_tokyo.csv を読み込んで配列に格納してから、
SJIS → UTF-8 の変換をしています。データが8行目からなので、
offset() で配列インデックス7を指定しています。項目名は5行目にあるので、
heads(4) で項目名一覧を取得しています。
1列目(8行目以降)が日付なので、column(0) で取得しています。
raw() は型変換無しの指定です。英語表記に変換するために $dictionary を使っていますが、
日本語のままで使う場合は、$dictionary を全て削ればOKです。
$dictionary[$heads[$x]] の箇所は $heads[$x] にすれば日本語になります。
$columns は、使用する項目の列の配列インデックスです。
pairs() で $columns の各要素について全ペアを取得し $pairs に格納しています。
$pairs についてループを回して散布図を生成しています。
では、実行してみましょう。
php -f Matrix.php > Matrix.md
examples/img/ 内に、 Matrix00.png ~ Matrix14.png が生成されています。
Matrix.md はMarkdown形式のファイルなので、VSCodeなどのプレビュー機能で確認できます。
Github上で表示させた場合の画面は次のような感じになります。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/scatterplot_matrix-1.png)
それぞれの散布図の下の「Properties」をクリックすると、parse() の結果が表示されます。
相関係数などを確認しながら、相関がありそうなのか確認できます。
各散布図をクリックすると散布図を見ることができます。
次の図は、平均気温と最高気温の散布図です。正の相関があることがわかります。
![](https://macocci7.net/blog/wp-content/uploads/2023/06/Matrix00-1.png)
このような感じの散布図が生成されています。
以上です。
(2024/03/10追記)Version 1.1.1 にアップデートしました。
詳細については、こちらの記事をご覧ください。
コメント