【Highcharts】ローレンツ曲線を描いてみる

Highcharts

高機能なグラフ描画用JavascriptライブラリHighchartsを使ってローレンツ曲線を描いてみました。

HichartsGPTが限界だった件

HichartsGPTにローレンツ曲線を描かせたら、さすがに基本的な描画はできました。

▼提示されたコード

Highcharts.chart('container', {
    chart: {
        type: 'line'
    },
    title: {
        text: 'ローレンツ曲線'
    },
    xAxis: {
        title: {
            text: '累積人口の割合'
        },
        labels: {
            format: '{value}%'
        }
    },
    yAxis: {
        title: {
            text: '累積所得の割合'
        },
        labels: {
            format: '{value}%'
        },
        max: 1
    },
    series: [{
        name: 'ローレンツ曲線',
        data: [
            [0, 0],
            [20, 0.1],
            [40, 0.3],
            [60, 0.5],
            [80, 0.7],
            [100, 1]
        ],
        marker: {
            enabled: false
        }
    }, {
        name: '完全平等線',
        data: [
            [0, 0],
            [100, 1]
        ],
        dashStyle: 'Dash'
    }]
});

▼実行結果

▼完全平等線とローレンツ曲線の間を塗りつぶしてね

⇒ ???それって単純な面グラフじゃね?

▼提示されたコード

Highcharts.chart('container', {
    chart: {
        type: 'area'
    },
    title: {
        text: 'ローレンツ曲線と完全平等線'
    },
    xAxis: {
        title: {
            text: '累積人口の割合'
        },
        labels: {
            format: '{value}%'
        }
    },
    yAxis: {
        title: {
            text: '累積所得の割合'
        },
        labels: {
            format: '{value}%'
        },
        max: 1
    },
    series: [{
        name: 'ローレンツ曲線',
        data: [
            [0, 0],
            [20, 0.1],
            [40, 0.3],
            [60, 0.5],
            [80, 0.7],
            [100, 1]
        ],
        marker: {
            enabled: false
        },
        fillColor: 'rgba(255, 165, 0, 0.5)' // オレンジ色で半透明
    }, {
        name: '完全平等線',
        data: [
            [0, 0],
            [100, 1]
        ],
        type: 'line',
        color: 'black',
        dashStyle: 'Dash'
    }]
});

▼実行結果

⇒ あ、やっぱり。。

その後問答を繰り返すも改善されることはなく、まったく同じコードを返してくる。。

ChatGPTの方が優秀だったよ

HighchartsGPTが限界のようなので、ChatGPTに訊いてみたら一発で解決しました。

▼「JavascriptライブラリのHighchartsを使ってローレンツ曲線を描き、完全平等線とローレンツ曲線の間をオレンジ色で塗りつぶしてください。」

▼提示されたコード

 ⇒ なんか余計な事してる感じですが、結果をみてOKなら見逃すことにします。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Lorenz Curve with Highcharts</title>
  <script src="https://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div id="container" style="width: 600px; height: 400px;"></div>

<script>
document.addEventListener('DOMContentLoaded', function () {
  // データ例(累積人口比, 累積所得比)
  const lorenzData = [
    [0, 0],
    [0.2, 0.05],
    [0.4, 0.15],
    [0.6, 0.35],
    [0.8, 0.65],
    [1, 1]
  ];

  // 完全平等線 y=x
  const equalityLine = lorenzData.map(([x, _]) => [x, x]);

  // arearange 用に [x, low, high] を生成(low = lorenz, high = equality)
  const areaData = lorenzData.map(([x, y], i) => [x, y, equalityLine[i][1]]);

  Highcharts.chart('container', {
    title: {
      text: 'ローレンツ曲線'
    },
    xAxis: {
      title: { text: '累積人口比' },
      min: 0,
      max: 1
    },
    yAxis: {
      title: { text: '累積所得比' },
      min: 0,
      max: 1
    },
    tooltip: {
      shared: true
    },
    series: [
      {
        type: 'line',
        name: '完全平等線',
        data: equalityLine,
        color: 'black',
        dashStyle: 'Dash'
      },
      {
        type: 'line',
        name: 'ローレンツ曲線',
        data: lorenzData,
        color: 'blue'
      },
      {
        type: 'arearange',
        name: '格差の領域',
        data: areaData,
        color: 'orange',
        fillOpacity: 0.4,
        lineWidth: 0,
        linkedTo: ':previous'
      }
    ]
  });
});
</script>
</body>
</html>

▼実行結果@JSFiddle

 ⇒ まあ、なんか余計な事してますが、さすがです!(オレンジマーカー要らない)

▼「ジニ係数もよろ」

▼提示されたコード

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Lorenz Curve with Gini Coefficient</title>
  <script src="https://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div id="container" style="width: 600px; height: 400px;"></div>

<script>
document.addEventListener('DOMContentLoaded', function () {
  // データ例(累積人口比, 累積所得比)
  const lorenzData = [
    [0, 0],
    [0.2, 0.05],
    [0.4, 0.15],
    [0.6, 0.35],
    [0.8, 0.65],
    [1, 1]
  ];

  // 完全平等線 y=x
  const equalityLine = lorenzData.map(([x, _]) => [x, x]);

  // arearange 用に [x, low, high]
  const areaData = lorenzData.map(([x, y], i) => [x, y, equalityLine[i][1]]);

  // --- ジニ係数の計算 ---
  // 台形公式でLorenz曲線下の面積を近似し、Gini = 1 - 2 * 面積
  let area = 0;
  for (let i = 1; i < lorenzData.length; i++) {
    const [x1, y1] = lorenzData[i - 1];
    const [x2, y2] = lorenzData[i];
    area += (x2 - x1) * (y1 + y2) / 2;
  }
  const gini = 1 - 2 * area;

  const chart = Highcharts.chart('container', {
    title: {
      text: 'ローレンツ曲線'
    },
    xAxis: {
      title: { text: '累積人口比' },
      min: 0,
      max: 1
    },
    yAxis: {
      title: { text: '累積所得比' },
      min: 0,
      max: 1
    },
    tooltip: {
      shared: true
    },
    series: [
      {
        type: 'line',
        name: '完全平等線',
        data: equalityLine,
        color: 'black',
        dashStyle: 'Dash'
      },
      {
        type: 'line',
        name: 'ローレンツ曲線',
        data: lorenzData,
        color: 'blue'
      },
      {
        type: 'arearange',
        name: '格差の領域',
        data: areaData,
        color: 'orange',
        fillOpacity: 0.4,
        lineWidth: 0,
        linkedTo: ':previous'
      }
    ]
  });

  // --- ジニ係数を表示 ---
  chart.renderer.text(
    'ジニ係数: ' + gini.toFixed(3),
    chart.xAxis[0].toPixels(0.05), // x=0.05付近
    chart.yAxis[0].toPixels(0.95)  // y=0.95付近
  )
  .css({
    color: 'red',
    fontSize: '14px',
    fontWeight: 'bold'
  })
  .add();
});
</script>
</body>
</html>

▼実行結果@JSFiddle

 ⇒ さすがです!

自分用に整形してみる

ChatGPTのアニキ、素晴らしい仕事してくれたけど、

  • オレンジのマーカーは要らないよね ⇒ marker: { enabled: false }
  • ジニ係数は少数2桁でイイよね ⇒ gini.toFixed(2)
  • 線の説明は要らないよね ⇒ name: ”
  • 凡例も要らないよね ⇒ legend: { enabled: false }
  • データエクスポートのハンバーガーメニューも要らないよね ⇒ exporting {enabled: false }
  • Highchartsのクレジットは消したいよね ⇒ credits: { enabled: false }

▼というわけで、これらを反映したもの

document.addEventListener('DOMContentLoaded', function () {
  // データ例(累積人口比, 累積所得比)
  const lorenzData = [
    [0, 0],
    [0.2, 0.05],
    [0.4, 0.15],
    [0.6, 0.35],
    [0.8, 0.65],
    [1, 1]
  ];

  // 完全平等線 y=x
  const equalityLine = lorenzData.map(([x, _]) => [x, x]);

  // arearange 用に [x, low, high]
  const areaData = lorenzData.map(([x, y], i) => [x, y, equalityLine[i][1]]);

  // --- ジニ係数の計算 ---
  // 台形公式でLorenz曲線下の面積を近似し、Gini = 1 - 2 * 面積
  let area = 0;
  for (let i = 1; i < lorenzData.length; i++) {
    const [x1, y1] = lorenzData[i - 1];
    const [x2, y2] = lorenzData[i];
    area += (x2 - x1) * (y1 + y2) / 2;
  }
  const gini = 1 - 2 * area;

  const chart = Highcharts.chart('container', {
    title: {
      text: 'ローレンツ曲線'
    },
    credits: { enabled: false },
    exporting: {enabled: false },
    legend: { enabled: false },
    xAxis: {
      title: { text: '累積人口比' },
      min: 0,
      max: 1
    },
    yAxis: {
      title: { text: '累積所得比' },
      min: 0,
      max: 1
    },
    tooltip: {
      shared: true
    },
    series: [
      {
        type: 'line',
        name: '',   // 完全平等線
        data: equalityLine,
        color: 'black',
        dashStyle: 'Dash',
        marker: { enabled: false }
      },
      {
        type: 'line',
        name: '',   // ローレンツ曲線
        data: lorenzData,
        color: 'blue',
        marker: { enabled: false }
      },
      {
        type: 'arearange',
        name: '',   // 格差の領域
        data: areaData,
        color: 'orange',
        fillOpacity: 0.4,
        lineWidth: 0,
        linkedTo: ':previous',
        marker: { enabled: false }
   }
    ]
  });

  // --- ジニ係数を表示 ---
  chart.renderer.text(
    'ジニ係数: ' + gini.toFixed(2),
    chart.xAxis[0].toPixels(0.05), // x=0.05付近
    chart.yAxis[0].toPixels(0.95)  // y=0.95付近
  )
  .css({
    color: 'blue',
    fontSize: '14px',
    fontWeight: 'bold'
  })
  .add();
});

▼実行結果@JSFiddle

こんな感じでシンプルになりました。

  • 0
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました