0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Grafanaで箱ひげ図(Boxplot)を描くーその2

Last updated at Posted at 2024-07-30

元データ

PostgreSQLでデータを作成

CREATE TABLE "成績" (
"学生番号"  varchar(255) not null,
"英語"      decimal(3,0),
"数学"      decimal(3,0),
"国語"      decimal(3,0),
PRIMARY KEY("学生番号")
);

INSERT INTO "成績" VALUES ('A01', 20, 20, 50);
INSERT INTO "成績" VALUES ('A02', 30, 25, 51);
INSERT INTO "成績" VALUES ('A03', 40, 30, 52);
INSERT INTO "成績" VALUES ('A04', 50, 35, 53);
INSERT INTO "成績" VALUES ('A05', 45, 40, 54);
INSERT INTO "成績" VALUES ('A06', 60, 45, 55);
INSERT INTO "成績" VALUES ('A07', 20, 50, 56);
INSERT INTO "成績" VALUES ('A08', 10, 55, 57);
INSERT INTO "成績" VALUES ('A09', 10, 60, 58);
INSERT INTO "成績" VALUES ('A10', 10, 65, 59);
INSERT INTO "成績" VALUES ('A11', 10, 70, 60);

Grafanaエディタ画面の左側、クエリーの設定

いたって普通の設定です。データソース選んで、テーブル選んで、カラムを選ぶ。
image.png

Grafanaエディタ画面の右側、Visual Editorの設定

Dataset Itemsに成績の科目のみ選びます。学生番号は選びません。
image.png

コード

感触としてはdatasetだけのコードが違うApache EChartsコードです。
Bussiness Chartsのサンプルコードでは以下の記述が多いですが、これだとdatasetは描画する直接の座標値データになるため、transformを入れた工夫が必要です。

return {
  dataset: context.editor.dataset,
  series: context.editor.series,
  xAxis: {
...

context.editor.dataset.sourceの1行目にはラベルが入っているので今回は邪魔なので別の変数に移動させて、X軸のラベル描画の際にその変数を用います。formatterのfunctionのparamsには値が0,1,2と入ってくるので配列のインデックス指定に使います。

// 最初の1行はラベル名、sourceから取り除く
mylabels = context.editor.dataset.source.shift();
//const mylabels = ['英語', '数学', '国語'];
  xAxis: {
    type: 'category',
    axisLabel: {
      formatter: function (params) {
        return mylabels[params];
      }
    }
  },

箱ひげ図の値データは1行の行データに変換する必要があるので行と列の変換を行います。
以下のコードはJavaScriptの行列交換のコード

// 行列交換
const transpose = a => a[0].map((_, c) => a.map(r => r[c]));
showdata = transpose(context.editor.dataset.source);

データはtransformオプションで箱ひげ図の元データとして計算させて描画させるデータへ変換させます。

    {
      // datasetindex is 1 
      fromDatasetIndex: 0,
      transform: {
        type: 'boxplot',
      },
    },

最終的なコードは以下の通り

// 最初の1行はラベル名、sourceから取り除く
mylabels = context.editor.dataset.source.shift();
//const mylabels = ['英語', '数学', '国語'];

// 行列交換
const transpose = a => a[0].map((_, c) => a.map(r => r[c]));
showdata = transpose(context.editor.dataset.source);

return {
  dataset: [
    {
      // datasetindex is 0 
      source: showdata,
    },
    {
      // datasetindex is 1 
      fromDatasetIndex: 0,
      transform: {
        type: 'boxplot',
      },
    },
  ],
  grid: {
    left: '10%',
    right: '10%',
    bottom: '15%'
  },
  series: {
    type: 'boxplot',
    datasetIndex: 1
  },
  xAxis: {
    type: 'category',
    axisLabel: {
      formatter: function (params) {
        return mylabels[params];
      }
    }
  },
  yAxis: {
    type: 'value',
    name: '点数',
    splitArea: {
      show: true
    }
  },
}

最初試したコード

クエリーから表示する前は以下のような感じでデータを直接コードに書きながらグラフが正しく表示されるか確認していました。

return {
  grid: {
    left: '10%',
    right: '10%',
    bottom: '15%'
  },
  dataset: [
    {
      // datasetindex=0
      source: [
        [74, 90, 107, 93, 85, 95, 98, 98, 88, 100, 98, 93, 65, 76],
        [24, 36, 44, 58, 60, 85, 88, 90, 84, 83, 79, 81, 88, 88],
        [88, 88, 86, 72, 72, 62, 86, 97, 95, 88, 91, 85, 87, 84],
        [81, 81, 82, 80, 77, 76, 74, 75, 76, 91, 92, 89, 86, 88],
      ]
    },
    {
      // datasetindex=1
      fromDatasetIndex: 0,
      transform: {
        type: 'boxplot',
        config: {
          itemNameFormatter: function (params) {
            if (params.value == 0) return '数学';
            if (params.value == 1) return '英語';
            if (params.value == 2) return '国語';
            if (params.value == 3) return '地理';
          }
        }
      },
    },
  ],
  series: {
    type: 'boxplot',
    datasetIndex: 1
  },
  xAxis: {
    type: 'category',
  },
  yAxis: {
    type: 'value',
    name: '点数',
    splitArea: {
      show: true
    }
  },
}

image.png

2系列、色を変える場合

こんな感じだと思います。Business ChartsのVisual Editorは1つのdatasetだけなので、複数のdatasetを使う場合はクエリーからVisual Editorへのデータセットをどうやって複数に分けるか考える必要があると思います。

const mylabels = ['英語', '数学', '国語'];

return {
  dataset: [
    {
      // dataset index = 0
      source: [
        [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
        [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
        [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
      ]
    },
    {
      // dataset index = 1
      source: [
        [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
        [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60],
        [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
      ]
    },
    {
      // dataset index = 2
      fromDatasetIndex: 0,
      transform: {
        type: 'boxplot',
      },
    },
    {
      // dataset index = 3
      fromDatasetIndex: 1,
      transform: { type: 'boxplot' },
    },
  ],
  grid: {
    left: '10%',
    right: '10%',
    bottom: '15%'
  },
  series: [
    {
      type: 'boxplot',
      name: 'boxplot1',
      itemStyle: {
        color: 'blue'
      },
      datasetIndex: 2
    },
    {
      type: 'boxplot',
      name: 'boxplot2',
      itemStyle: {
        color: 'white'
      },
      datasetIndex: 3
    },
  ],
  xAxis: {
    type: 'category',
    axisLabel: {
      formatter: function (params) {
        return mylabels[params];
      }
    }
    // datasetを使うと、ここでdataは使えない
    // data: ['英語', '数学', '社会']
  },
  yAxis: {
    type: 'value',
    name: '点数',
    splitArea: {
      show: true
    }
  },
}

image.png

Grafanaで箱ひげ図(Boxplot)を描く-その1

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?