人口分布マップチャートライブラリ比較

地理的な位置情報と人口データをバブルマップで可視化し、3つのアプローチを比較

このページについて: 地理的な座標(緯度・経度)を軸にバブルを配置する「地図型バブル表現」を扱います。 任意のXY軸で3変数を比較する汎用的なバブルチャートは バブルチャート(Bubble Chart) を参照してください。

📊 使用しているサンプルデータ

日本の8地方区分+沖縄の人口データを使用しています。バブルのサイズは人口に比例し、位置は各地方の代表的な経緯度に基づいています。

[
  {
    "region": "北海道",
    "population": 522,
    "density": 63,
    "x": 143.2,
    "y": 43.1
  },
  {
    "region": "東北",
    "population": 862,
    "density": 129,
    "x": 140.3,
    "y": 39.5
  },
  {
    "region": "関東",
    "population": 4349,
    "density": 1348,
    "x": 139.7,
    "y": 36
  },
  {
    "region": "中部",
    "population": 2128,
    "density": 314,
    "x": 137,
    "y": 36.2
  },
  {
    "region": "近畿",
    "population": 2229,
    "density": 667,
    "x": 135.5,
    "y": 34.7
  },
  {
    "region": "中国",
    "population": 719,
    "density": 227,
    "x": 132.5,
    "y": 34.5
  },
  {
    "region": "四国",
    "population": 372,
    "density": 198,
    "x": 133.5,
    "y": 33.8
  },
  {
    "region": "九州",
    "population": 1282,
    "density": 304,
    "x": 131,
    "y": 33
  },
  {
    "region": "沖縄",
    "population": 146,
    "density": 641,
    "x": 127.7,
    "y": 26.3
  }
]

1. カスタム React 実装(SVG バブルマップ)

React + SVGでカスタム実装したバブルマップ。地理的な配置と人口密度による色分けで直感的な人口分布を表現。

✓ 地図的レイアウト✓ 密度色分け✓ 依存ゼロ
~100~200~500~10001000+(人/km²)
128°E132°E136°E140°E144°E28°N32°N36°N40°N44°N関東4,349近畿2,229中部2,128九州1,282東北862中国719北海道522四国372沖縄146

バブルのサイズ = 人口(万人)、色 = 人口密度(人/km²)

特徴: ライブラリに依存せず、地理的な位置関係と人口密度の色分けを組み合わせた直感的なバブルマップ。バブルサイズと色の二重エンコーディングで情報密度が高い。
tsx
'use client';
// React + SVGのみでバブルマップを実装(外部ライブラリ不要)
const sampleData = [
  { region: '北海道', population: 522,  density: 63,   x: 143.2, y: 43.1 },
  { region: '東北',   population: 862,  density: 129,  x: 140.3, y: 39.5 },
  { region: '関東',   population: 4349, density: 1348, x: 139.7, y: 36.0 },
  { region: '中部',   population: 2128, density: 314,  x: 137.0, y: 36.2 },
  { region: '近畿',   population: 2229, density: 667,  x: 135.5, y: 34.7 },
  { region: '中国',   population: 719,  density: 227,  x: 132.5, y: 34.5 },
  { region: '四国',   population: 372,  density: 198,  x: 133.5, y: 33.8 },
  { region: '九州',   population: 1282, density: 304,  x: 131.0, y: 33.0 },
  { region: '沖縄',   population: 146,  density: 641,  x: 127.7, y: 26.3 },
];

const maxPopulation = Math.max(...sampleData.map((d) => d.population));

function mapX(lon: number) { return ((lon - 126) / (146 - 126)) * 440 + 40; }
function mapY(lat: number) { return 400 - ((lat - 25) / (45 - 25)) * 360 + 20; }
function getRadius(pop: number) { return Math.sqrt(pop / maxPopulation) * 32 + 4; }
function getColor(density: number) {
  if (density > 1000) return 'rgba(239,68,68,0.75)';
  if (density > 500)  return 'rgba(249,115,22,0.7)';
  if (density > 200)  return 'rgba(234,179,8,0.65)';
  if (density > 100)  return 'rgba(16,185,129,0.65)';
  return 'rgba(59,130,246,0.65)';
}

export function CustomSvgBubbleMap() {
  return (
    <svg viewBox="0 0 520 420" className="w-full max-w-lg">
      {sampleData.map((d) => (
        <circle key={d.region}
          cx={mapX(d.x)} cy={mapY(d.y)}
          r={getRadius(d.population)}
          fill={getColor(d.density)}
          stroke="white" strokeWidth={1}>
          <title>{d.region} 人口:{d.population}万人 密度:{d.density}人/km²</title>
        </circle>
      ))}
      {sampleData.map((d) => (
        <text key={d.region + '-label'}
          x={mapX(d.x)} y={mapY(d.y) + getRadius(d.population) + 12}
          textAnchor="middle" fontSize={9} fill="#374151">{d.region}</text>
      ))}
    </svg>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、カスタムReact実装(SVGバブルマップ)を使った人口分布マップを実装してください。

- 使用ライブラリ: 外部ライブラリなし。React + SVGのみで経緯度→SVG座標変換・バブルサイズ計算・色分けをすべて自前実装すること
- サンプルデータ: 日本の地域別人口分布9地域(緯度・経度・人口・人口密度)を用意すること
- インタラクティブ: SVG の title 要素を使って各バブルにホバーツールチップを実装すること
- バブルサイズ: Math.sqrt(population / maxPopulation) * スケール係数 + 最小半径 でサイズを計算すること
- 地図表示: 日本列島のGeoJSONアウトライン座標をSVGの path 要素で背景描画すること
- スタイリング: 人口密度に応じて5段階の色を設定し、バブルサイズと色の二重エンコーディングで情報密度を高めること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

2. Nivo (@nivo/scatterplot)

ScatterPlotの動的ノードサイズ機能でバブルマップを実現。東日本・西日本のグループ分けで地域の対比を表現。

✓ 動的ノードサイズ✓ インタラクティブ✓ D3.jsベース
特徴: nodeSize設定で人口に応じたバブルサイズの動的変更が可能。メッシュベースのインタラクションでホバー時の情報表示がスムーズ。
tsx
'use client';
import { ResponsiveScatterPlot } from '@nivo/scatterplot';

const data = [
  {
    id: '東日本',
    data: [
      { x: 143.2, y: 43.1, population: 522,  region: '北海道', density: 63   },
      { x: 140.3, y: 39.5, population: 862,  region: '東北',   density: 129  },
      { x: 139.7, y: 36.0, population: 4349, region: '関東',   density: 1348 },
      { x: 137.0, y: 36.2, population: 2128, region: '中部',   density: 314  },
    ],
  },
  {
    id: '西日本',
    data: [
      { x: 135.5, y: 34.7, population: 2229, region: '近畿', density: 667 },
      { x: 132.5, y: 34.5, population: 719,  region: '中国', density: 227 },
      { x: 133.5, y: 33.8, population: 372,  region: '四国', density: 198 },
      { x: 131.0, y: 33.0, population: 1282, region: '九州', density: 304 },
      { x: 127.7, y: 26.3, population: 146,  region: '沖縄', density: 641 },
    ],
  },
];

const maxPopulation = 4349;

export function NivoPopulationMap() {
  return (
    <div style={{ height: 400 }}>
      <ResponsiveScatterPlot
        data={data}
        margin={{ top: 20, right: 120, bottom: 60, left: 70 }}
        xScale={{ type: 'linear', min: 125, max: 146 }}
        yScale={{ type: 'linear', min: 24, max: 46 }}
        nodeSize={(datum: any) => Math.sqrt(datum.data.population / maxPopulation) * 32 + 4}
        axisBottom={{ legend: '経度', legendPosition: 'middle', legendOffset: 46 }}
        axisLeft={{ legend: '緯度', legendPosition: 'middle', legendOffset: -56 }}
        colors={['#3b82f6', '#10b981']}
        useMesh={true}
        tooltip={({ node }: any) => (
          <div style={{ background: 'white', padding: '8px', border: '1px solid #ccc', borderRadius: 4 }}>
            <strong>{node.data.region}</strong><br />
            人口: {node.data.population}万人<br />
            密度: {node.data.density}人/km²
          </div>
        )}
      />
    </div>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、Nivo(@nivo/scatterplot)を使った人口分布バブルマップを実装してください。

- 使用ライブラリ: @nivo/scatterplot の ResponsiveScatterPlot コンポーネント
- サンプルデータ: 日本の地域別人口分布9地域を東日本・西日本の2グループに分けた { id, data: [{ x, y, population, region, density }] } 形式で用意すること
- インタラクティブ: tooltip プロパティでカスタムツールチップを実装し、地域名・人口・人口密度を表示すること
- バブルサイズ: nodeSize 関数で population に応じた動的なノードサイズを計算すること
- 地図表示: layers プロパティにカスタムレイヤーを追加し、xScale・yScale を使って日本列島アウトラインをSVGで描画すること
- スタイリング: useMesh={true} でメッシュベースのインタラクションを有効化し、東日本・西日本を色分けすること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

3. Chart.js (Bubble Chart)

Chart.jsのネイティブBubbleチャートを活用。Canvas APIによる高パフォーマンスなレンダリングで大量データも安定。

✓ ネイティブBubble✓ Canvas高速描画✓ 軸ラベル対応
特徴: Chart.jsのBubbleチャートはrプロパティでバブルサイズを直接指定。Canvas APIを活用するためデータポイントが増えてもパフォーマンスが安定。
tsx
'use client';
import { Bubble } from 'react-chartjs-2';
import { Chart as ChartJS, LinearScale, PointElement, Tooltip, Legend } from 'chart.js';

ChartJS.register(LinearScale, PointElement, Tooltip, Legend);

const maxPopulation = 4349;
function r(pop: number) { return Math.sqrt(pop / maxPopulation) * 20 + 3; }

const data = {
  datasets: [
    {
      label: '東日本',
      data: [
        { x: 143.2, y: 43.1, r: r(522),  region: '北海道', population: 522  },
        { x: 140.3, y: 39.5, r: r(862),  region: '東北',   population: 862  },
        { x: 139.7, y: 36.0, r: r(4349), region: '関東',   population: 4349 },
        { x: 137.0, y: 36.2, r: r(2128), region: '中部',   population: 2128 },
      ],
      backgroundColor: 'rgba(59,130,246,0.5)',
    },
    {
      label: '西日本',
      data: [
        { x: 135.5, y: 34.7, r: r(2229), region: '近畿', population: 2229 },
        { x: 132.5, y: 34.5, r: r(719),  region: '中国', population: 719  },
        { x: 133.5, y: 33.8, r: r(372),  region: '四国', population: 372  },
        { x: 131.0, y: 33.0, r: r(1282), region: '九州', population: 1282 },
        { x: 127.7, y: 26.3, r: r(146),  region: '沖縄', population: 146  },
      ],
      backgroundColor: 'rgba(16,185,129,0.5)',
    },
  ],
};

export function ChartJSPopulationMap() {
  return (
    <Bubble data={data} options={{
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        tooltip: {
          callbacks: {
            label: (ctx: any) => {
              const d = ctx.raw;
              return [`${d.region}`, `人口: ${d.population}万人`];
            },
          },
        },
      },
      scales: {
        x: { min: 125, max: 147, title: { display: true, text: '経度' } },
        y: { min: 24,  max: 46,  title: { display: true, text: '緯度' } },
      },
    }} height={400} />
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、Chart.js(react-chartjs-2 Bubble)を使った人口分布バブルマップを実装してください。

- 使用ライブラリ: chart.js と react-chartjs-2 の Bubble コンポーネント。LinearScale・PointElement・Tooltip・Legend を ChartJS.register で登録すること
- サンプルデータ: 日本の地域別人口分布9地域を東日本・西日本に分け、{ x: 経度, y: 緯度, r: バブル半径, region, population, density } 形式で用意すること
- インタラクティブ: options.plugins.tooltip.callbacks.label でカスタムツールチップを実装し、地域名・人口・人口密度を表示すること
- バブルサイズ: r プロパティに Math.sqrt(population / maxPopulation) * スケール係数 を設定すること
- 地図表示: Chart.jsプラグイン(beforeDatasetsDraw)でCanvas APIを使って日本列島アウトラインを背景描画すること
- スタイリング: responsive: true・maintainAspectRatio: false を設定し、東日本・西日本をそれぞれ別色で塗り分けること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

4. Recharts (ScatterChart + ZAxis)

ScatterChartのZAxisを活用してバブルサイズを制御。Reactの宣言的APIで直感的なコード記述が可能。

✓ ZAxis対応✓ 宣言的API✓ レスポンシブ
特徴: ZAxisでバブルサイズの範囲を宣言的に指定でき、複数のScatterコンポーネントを重ねることでグループ分けも容易。カスタムツールチップで詳細情報を表示。
tsx
'use client';
import {
  ScatterChart, Scatter, XAxis, YAxis, ZAxis,
  Tooltip, Legend, ResponsiveContainer,
} from 'recharts';

const eastJapan = [
  { x: 143.2, y: 43.1, population: 522,  region: '北海道', density: 63   },
  { x: 140.3, y: 39.5, population: 862,  region: '東北',   density: 129  },
  { x: 139.7, y: 36.0, population: 4349, region: '関東',   density: 1348 },
  { x: 137.0, y: 36.2, population: 2128, region: '中部',   density: 314  },
];

const westJapan = [
  { x: 135.5, y: 34.7, population: 2229, region: '近畿', density: 667 },
  { x: 132.5, y: 34.5, population: 719,  region: '中国', density: 227 },
  { x: 133.5, y: 33.8, population: 372,  region: '四国', density: 198 },
  { x: 131.0, y: 33.0, population: 1282, region: '九州', density: 304 },
  { x: 127.7, y: 26.3, population: 146,  region: '沖縄', density: 641 },
];

export function RechartsPopulationMap() {
  return (
    <ResponsiveContainer width="100%" height={400}>
      <ScatterChart margin={{ top: 20, right: 20, bottom: 40, left: 40 }}>
        <XAxis type="number" dataKey="x" name="経度" domain={[125, 147]}
          label={{ value: '経度', position: 'insideBottom', offset: -5 }} />
        <YAxis type="number" dataKey="y" name="緯度" domain={[24, 46]}
          label={{ value: '緯度', angle: -90, position: 'insideLeft' }} />
        <ZAxis type="number" dataKey="population" range={[50, 2000]} />
        <Tooltip cursor={{ strokeDasharray: '3 3' }} />
        <Legend verticalAlign="top" />
        <Scatter name="東日本" data={eastJapan} fill="#3b82f6" fillOpacity={0.6} />
        <Scatter name="西日本" data={westJapan} fill="#10b981" fillOpacity={0.6} />
      </ScatterChart>
    </ResponsiveContainer>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、Recharts(ScatterChart + ZAxis)を使った人口分布バブルマップを実装してください。

- 使用ライブラリ: recharts の ScatterChart・Scatter・XAxis・YAxis・ZAxis・CartesianGrid・Tooltip・Legend・ResponsiveContainer・Customized コンポーネント
- サンプルデータ: 日本の地域別人口分布9地域を東日本・西日本に分け、{ x: 経度, y: 緯度, population, density, region } 形式で用意すること
- インタラクティブ: Tooltip の content プロパティにカスタムコンポーネントを渡し、地域名・人口・人口密度を表示すること
- バブルサイズ: ZAxis の dataKey="population"・range={[最小面積, 最大面積]} でバブルサイズを宣言的に制御すること
- 地図表示: Customized コンポーネントで xAxisMap・yAxisMap のスケール関数を取得し、日本列島アウトラインをSVGで背景描画すること
- スタイリング: 東日本・西日本を Scatter コンポーネントで分けて異なる fill 色を設定すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

ライブラリ比較

アプローチレンダリングバブルサイズ制御地図的表現おすすめ用途
カスタム React (SVG)SVG◎(完全自由)独自デザインのマップ
NivoSVG◎(動的nodeSize)分析ダッシュボード
Chart.jsCanvas◯(rプロパティ)大量データ・高速描画
RechartsSVG◯(ZAxis)Reactプロジェクト全般

選択のポイント

  • カスタム React (SVG): 地図的なレイアウトや密度による色分けなど、独自のビジュアル表現が必要な場合。依存ゼロでバンドルサイズへの影響もなし。
  • Nivo: 動的nodeSize設定で手軽にバブルマップを実現。メッシュベースのインタラクションとカスタムツールチップで高い操作性。
  • Chart.js: ネイティブBubbleチャートで簡潔な実装。Canvas描画により数百のデータポイントでもパフォーマンスが安定。
  • Recharts: ZAxisによるバブルサイズ制御が宣言的。既にRechartsを使用しているプロジェクトへの統合が容易。