バブルチャートライブラリ比較

3変数(X軸・Y軸・バブルサイズ)を同時に可視化し、散布図を拡張したバブルチャートの実装を3ライブラリで比較

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

2事業部の製品ポートフォリオ分析データ(各4件)を使用しています。 X軸:売上高(万円)、Y軸:利益率(%)、バブルサイズ:市場シェア(%)の3変数を同時に表現します。

{
  "divisionA": [
    {
      "sales": 1200,
      "profit": 18,
      "share": 15
    },
    {
      "sales": 850,
      "profit": 12,
      "share": 8
    }
  ],
  "divisionB": [
    {
      "sales": 1680,
      "profit": 20,
      "share": 17
    },
    {
      "sales": 950,
      "profit": 15,
      "share": 10
    }
  ],
  "note": "sales=売上高(万円), profit=利益率(%), share=市場シェア(%)"
}

1. Recharts

ScatterChart + ZAxisの組み合わせで第3変数をバブルサイズに直感的にマッピング

✓ ZAxis対応✓ 複数系列✓ レスポンシブ
特徴: ZAxisにdataKeyを設定するだけで第3変数をバブルサイズに変換可能。 rangeプロパティでバブルの最小・最大サイズを制御できます。
tsx
'use client';
import {
  ScatterChart, Scatter, XAxis, YAxis, ZAxis,
  CartesianGrid, Tooltip, Legend, ResponsiveContainer,
} from 'recharts';

const divisionA = [
  { sales: 1200, profit: 18, share: 15 },
  { sales: 850,  profit: 12, share: 8  },
  { sales: 2100, profit: 25, share: 22 },
  { sales: 450,  profit: 8,  share: 4  },
];

const divisionB = [
  { sales: 1680, profit: 20, share: 17 },
  { sales: 950,  profit: 15, share: 10 },
  { sales: 720,  profit: 6,  share: 6  },
  { sales: 3200, profit: 30, share: 28 },
];

export function RechartsBubbleChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <ScatterChart>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis type="number" dataKey="sales" name="売上高" unit="万円"
          label={{ value: '売上高(万円)', position: 'insideBottom', offset: -5, fontSize: 11 }} />
        <YAxis type="number" dataKey="profit" name="利益率" unit="%"
          label={{ value: '利益率(%)', angle: -90, position: 'insideLeft', fontSize: 11 }} />
        <ZAxis type="number" dataKey="share" name="市場シェア" unit="%" range={[50, 1000]} />
        <Tooltip cursor={{ strokeDasharray: '3 3' }} />
        <Legend verticalAlign="top" />
        <Scatter name="事業部A" data={divisionA} fill="#3b82f6" fillOpacity={0.6} />
        <Scatter name="事業部B" data={divisionB} fill="#10b981" fillOpacity={0.6} />
      </ScatterChart>
    </ResponsiveContainer>
  );
}

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

React + Tailwind CSSで、Rechartsを使ったバブルチャートを実装してください。

- 使用ライブラリ: recharts(ScatterChart、Scatter、XAxis、YAxis、ZAxis、CartesianGrid、Tooltip、Legend、ResponsiveContainer)
- サンプルデータ: 2事業部の売上高・利益率・市場シェア(各4件)を用意すること
- 第3変数: ZAxisのdataKeyで市場シェアをバブルサイズにマッピングすること(range=[50, 1000])
- インタラクティブ: ホバー時にツールチップで3変数の値(単位付き)を表示すること
- グループ区別: Scatterコンポーネントを複数配置し、fillカラーで事業部ごとに色分けして表示すること
- レスポンシブ: ResponsiveContainerで親要素の幅に応じてチャートサイズが変わるよう対応すること
- 透明度: fillOpacityを0.6に設定してバブルの重なりを見やすくすること

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

2. Nivo

ResponsiveScatterPlotのnodeSizeに関数を渡して市場シェアを動的にバブルサイズへ変換

✓ 動的nodeSize✓ 美しいデフォルト✓ D3.jsパワー
特徴: nodeSizeプロパティに関数を渡すことでデータ値に応じたバブルサイズを実現。 D3.jsの豊富な機能を活かした美しいデフォルトデザインと高度なインタラクションが特徴です。
tsx
'use client';
import { ResponsiveScatterPlot } from '@nivo/scatterplot';

const data = [
  {
    id: '事業部A',
    data: [
      { x: 1200, y: 18, share: 15 },
      { x: 850,  y: 12, share: 8  },
      { x: 2100, y: 25, share: 22 },
      { x: 450,  y: 8,  share: 4  },
    ],
  },
  {
    id: '事業部B',
    data: [
      { x: 1680, y: 20, share: 17 },
      { x: 950,  y: 15, share: 10 },
      { x: 720,  y: 6,  share: 6  },
      { x: 3200, y: 30, share: 28 },
    ],
  },
];

export function NivoBubbleChart() {
  return (
    <div style={{ height: 300 }}>
      <ResponsiveScatterPlot
        data={data}
        margin={{ top: 20, right: 120, bottom: 60, left: 70 }}
        xScale={{ type: 'linear', min: 0, max: 'auto' }}
        yScale={{ type: 'linear', min: 0, max: 'auto' }}
        nodeSize={(datum: any) => datum.data.share * 1.5 + 5}
        axisBottom={{ legend: '売上高(万円)', legendPosition: 'middle', legendOffset: 46 }}
        axisLeft={{ legend: '利益率(%)', legendPosition: 'middle', legendOffset: -56 }}
        colors={['#3b82f6', '#10b981']}
        useMesh={false}
        legends={[{ anchor: 'bottom-right', direction: 'column', itemWidth: 80, itemHeight: 20 }]}
      />
    </div>
  );
}

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

React + Tailwind CSSで、Nivoを使ったバブルチャートを実装してください。

- 使用ライブラリ: @nivo/scatterplot(ResponsiveScatterPlot)
- サンプルデータ: 2事業部の売上高・利益率・市場シェア(各4件)をNivo形式({id, data: [{x, y, share}]})で用意すること
- 第3変数: nodeSizeプロパティに関数を設定し、市場シェアをバブルサイズに動的マッピングすること(例: (datum) => datum.data.share * 1.5 + 5)
- インタラクティブ: ホバー時にツールチップで3変数の値を表示すること(useMesh: true)
- グループ区別: colorsプロパティで事業部ごとに色分けし、凡例を表示すること
- 軸ラベル: axisBottomとaxisLeftのlegendプロパティで軸のラベル(売上高・利益率)を表示すること
- 透明度: blendModeを "multiply" またはopacityで重なりを見やすくすること

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

3. Chart.js (react-chartjs-2)

専用のBubbleチャートタイプでデータの r プロパティがバブル半径(ピクセル)を直接制御

✓ Bubble専用タイプ✓ Canvas高速描画✓ 大量データ対応
特徴: データに r(radius)を含めるだけで動作するシンプルな実装。 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 data = {
  datasets: [
    {
      label: '事業部A',
      data: [
        { x: 1200, y: 18, r: 15 * 0.6 + 3 },
        { x: 850,  y: 12, r: 8  * 0.6 + 3 },
        { x: 2100, y: 25, r: 22 * 0.6 + 3 },
        { x: 450,  y: 8,  r: 4  * 0.6 + 3 },
      ],
      backgroundColor: 'rgba(59, 130, 246, 0.5)',
      borderColor: 'rgba(59, 130, 246, 1)',
    },
    {
      label: '事業部B',
      data: [
        { x: 1680, y: 20, r: 17 * 0.6 + 3 },
        { x: 950,  y: 15, r: 10 * 0.6 + 3 },
        { x: 720,  y: 6,  r: 6  * 0.6 + 3 },
        { x: 3200, y: 30, r: 28 * 0.6 + 3 },
      ],
      backgroundColor: 'rgba(16, 185, 129, 0.5)',
      borderColor: 'rgba(16, 185, 129, 1)',
    },
  ],
};

export function ChartJSBubbleChart() {
  return (
    <Bubble data={data} options={{
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        x: { title: { display: true, text: '売上高(万円)' } },
        y: { title: { display: true, text: '利益率(%)' } },
      },
    }} height={300} />
  );
}

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

React + Tailwind CSSで、Chart.js(react-chartjs-2)を使ったバブルチャートを実装してください。

- 使用ライブラリ: react-chartjs-2(Bubble)、chart.js(LinearScale、PointElement、Tooltip、Legend)
- サンプルデータ: 2事業部の売上高・利益率・市場シェア(各4件)を{x, y, r}形式で用意すること(rは市場シェアを適切なピクセル値に変換:例 share * 0.6 + 3)
- 第3変数: データの r プロパティでバブルの半径(ピクセル)を制御すること
- インタラクティブ: ホバー時にツールチップで3変数の値を表示すること
- グループ区別: datasetsを事業部ごとに分けてbackgroundColorとborderColorで色分けして表示すること
- レスポンシブ: responsive: true、maintainAspectRatio: falseで親要素に合わせてサイズを調整すること
- 軸ラベル: scalesのx・yそれぞれにtitle.display: trueと軸名(売上高・利益率)を設定すること

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

4. Victory

VictoryScatterのbubblePropertyで第3変数をバブルサイズに宣言的にマッピング。SVGベースのモジュール式設計

✓ bubbleProperty対応✓ SVGベース✓ モジュール式
事業部A事業部B売上高(万円)5001,0001,5002,0002,5003,000利益率(%)1015202530
特徴: bubblePropertyにデータキーを指定するだけでバブルサイズを制御可能。 モジュール式設計により必要なコンポーネントだけを組み合わせて使え、TypeScriptサポートも充実。
tsx
'use client';
import {
  VictoryChart, VictoryScatter, VictoryAxis,
  VictoryTooltip, VictoryLegend, VictoryTheme,
} from 'victory';

const dataA = [
  { x: 1200, y: 18, z: 15 },
  { x: 850,  y: 12, z: 8  },
  { x: 2100, y: 25, z: 22 },
  { x: 450,  y: 8,  z: 4  },
];

const dataB = [
  { x: 1680, y: 20, z: 17 },
  { x: 950,  y: 15, z: 10 },
  { x: 720,  y: 6,  z: 6  },
  { x: 3200, y: 30, z: 28 },
];

export function VictoryBubbleChart() {
  return (
    <VictoryChart theme={VictoryTheme.clean} height={280}
      padding={{ top: 20, bottom: 60, left: 70, right: 40 }}>
      <VictoryLegend x={60} y={5} orientation="horizontal" gutter={20}
        data={[
          { name: '事業部A', symbol: { fill: 'rgba(59,130,246,0.6)' } },
          { name: '事業部B', symbol: { fill: 'rgba(16,185,129,0.6)' } },
        ]} />
      <VictoryAxis label="売上高(万円)"
        style={{ axisLabel: { padding: 40 } }} />
      <VictoryAxis dependentAxis label="利益率(%)"
        style={{ axisLabel: { padding: 50 } }} />
      <VictoryScatter bubbleProperty="z" maxBubbleSize={25} minBubbleSize={5}
        data={dataA}
        style={{ data: { fill: 'rgba(59,130,246,0.6)', stroke: '#3b82f6', strokeWidth: 1.5 } }}
        labelComponent={<VictoryTooltip />}
        labels={({ datum }) => `売上高: ${datum.x}万円 利益率: ${datum.y}%`} />
      <VictoryScatter bubbleProperty="z" maxBubbleSize={25} minBubbleSize={5}
        data={dataB}
        style={{ data: { fill: 'rgba(16,185,129,0.6)', stroke: '#10b981', strokeWidth: 1.5 } }}
        labelComponent={<VictoryTooltip />}
        labels={({ datum }) => `売上高: ${datum.x}万円 利益率: ${datum.y}%`} />
    </VictoryChart>
  );
}

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

React + Tailwind CSSで、Victoryを使ったバブルチャートを実装してください。

- 使用ライブラリ: victory(VictoryChart、VictoryScatter、VictoryAxis、VictoryTooltip、VictoryLegend)
- サンプルデータ: 2事業部の売上高・利益率・市場シェア(各4件)を{x, y, z}形式で用意すること(z = 市場シェア)
- 第3変数: VictoryScatterのbubblePropertyに "z" を設定し、maxBubbleSize・minBubbleSizeでサイズ範囲を制御すること
- インタラクティブ: labelComponentにVictoryTooltipを設定し、labelsプロパティで3変数の値を表示すること
- グループ区別: VictoryScatterを2つ配置し、styleのdata.fillで事業部ごとに色分けすること
- 凡例: VictoryLegendコンポーネントでグループ名と色を表示すること
- 軸ラベル: VictoryAxisのlabelプロパティで軸名(売上高・利益率)を設定すること

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

ライブラリ比較

ライブラリ第3変数対応インタラクションスケール制御おすすめ用途
Recharts◎(ZAxis)◯(range指定)ダッシュボード
Nivo◯(nodeSize関数)◎(関数で自由設定)分析レポート
Chart.js◎(r値)△(ピクセル直指定)大量データの可視化
Victory◎(bubbleProperty)◯(min/maxBubbleSize)モジュール式カスタマイズ

バブルチャートの選択ポイント

  • Recharts: ZAxisのdataKeyとrangeで第3変数を直感的に設定可能。 Reactプロジェクトのダッシュボードや管理画面に最適。
  • Nivo: nodeSizeに関数を渡すことでスケールを自由にカスタマイズ可能。 美しいアニメーションと高度なインタラクションを求める分析レポートに最適。
  • Chart.js: 専用のBubbleチャートタイプでシンプルに実装可能。 Canvas描画で大量データでも高パフォーマンスを維持。ただしrはピクセル値のため データスケールへの変換が必要。
  • Victory: bubblePropertyにデータキーを指定するだけで第3変数のバブルサイズ化が完結。 モジュール式設計でコンポーネントを自由に組み合わせられ、 TypeScriptサポートも充実。D3非依存で軽量。

バブルチャートの典型的な使用例

📦 製品ポートフォリオ分析

売上・利益率・市場シェアの3変数で各製品の位置づけを俯瞰的に把握

🌍 国別・地域別比較

GDP・一人当たり所得・人口の3変数で国の経済状況を比較(バブルサイズ=人口)

👥 顧客セグメント分析

購買頻度・平均単価・顧客数で顧客グループの特性と規模を同時に可視化

⚠️ リスクマトリクス

発生確率・影響度・対応コストでリスクの優先度を視覚的に評価

⚠️ バブルチャート使用時の注意点

  • バブルサイズは面積ではなく半径で比較してしまいがちなため、凡例でスケールを明示する
  • バブルが重なる場合は透明度(opacity)を調整して後ろのバブルも視認できるようにする
  • 散布図と同じく相関関係と因果関係を混同しないよう注意する
  • バブルサイズの差が大きすぎると小さいバブルが見えにくくなるためrangeや最小サイズを適切に設定する
  • 地理座標ベースのバブルマップには別途マップライブラリ(Leaflet等)の利用を検討する