mcpField
M
mapbox-data-visualization-patterns

mapbox-data-visualization-patterns

github.com/mapboxデータ・データベース832.1k 回インストール4 週間前に更新
リポジトリ

mapbox-data-visualization-patterns について

Mapboxの地図でデータを可視化する開発者向けのパターンガイドです。コロプレス図、ヒートマップ、3D表現、データ駆動型スタイルに加え、大規模データの性能改善も扱います。

主な機能

  1. 01コロプレス図
  2. 02ヒートマップとポイントクラスタリング
  3. 033D押し出しとデータ駆動型スタイル
  4. 04時系列アニメーション
  5. 05大規模データセットの性能調整
  6. 06凡例と可視化の参考資料

活用シーン

  1. 01地域ごとの人口や売上を比較する場面
  2. 02イベント地点の密度を示す場面
  3. 03プロパティに応じて地図要素をスタイル設定する場面
  4. 04時間とともに変化するデータを表示する場面
  5. 05大規模な地図データの読み込みと描画を最適化する場面

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-data-visualization-patterns

インストール後、Claude Code で/mapbox-data-visualization-patternsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

AGENTS.md
evals/
evals.json
references/
3d-extrusions.md
animation.md
circles-lines.md
clustering.md
legends-use-cases.md
performance.md

詳細

データ可視化パターンのスキル

Mapbox マップでデータを可視化するための包括的なパターンです。コロプレスマップ、ヒートマップ、3D 押し出し、データ駆動型スタイリング、アニメーションによる可視化、データ量の多いアプリケーション向けのパフォーマンス最適化を扱います。

このスキルを使用する場面

次のような場合に、このスキルを使用します。

  • マップ上で統計データ(人口、売上、人口統計など)を可視化する
  • 色分けされた地域でコロプレスマップを作成する
  • 密度を可視化するためのヒートマップやクラスタリングを構築する
  • 3D 可視化(建物の高さ、地形の標高など)を追加する
  • プロパティに基づくデータ駆動型スタイリングを実装する
  • 時系列データをアニメーション化する
  • 最適化が必要な大規模なデータセットを扱う

可視化の種類

コロプレスマップ

最適な用途: 地域データ(州、郡、郵便番号)、統計上の比較

パターン: データ値に基づいてポリゴンを色分けします

map.on('load', () => {
  // Add data source (GeoJSON with properties)
  map.addSource('states', {
    type: 'geojson',
    data: 'https://example.com/states.geojson' // Features with population property
  });

  // Add fill layer with data-driven color
  map.addLayer({
    id: 'states-layer',
    type: 'fill',
    source: 'states',
    paint: {
      'fill-color': [
        'interpolate',
        ['linear'],
        ['get', 'population'],
        0,
        '#f0f9ff', // Light blue for low population
        500000,
        '#7fcdff',
        1000000,
        '#0080ff',
        5000000,
        '#0040bf', // Dark blue for high population
        10000000,
        '#001f5c'
      ],
      'fill-opacity': 0.75
    }
  });

  // Add border layer
  map.addLayer({
    id: 'states-border',
    type: 'line',
    source: 'states',
    paint: {
      'line-color': '#ffffff',
      'line-width': 1
    }
  });

  // Add hover effect with reusable popup
  const popup = new mapboxgl.Popup({
    closeButton: false,
    closeOnClick: false
  });

  map.on('mousemove', 'states-layer', (e) => {
    if (e.features.length > 0) {
      map.getCanvas().style.cursor = 'pointer';

      const feature = e.features[0];
      popup
        .setLngLat(e.lngLat)
        .setHTML(
          `
          <h3>${feature.properties.name}</h3>
          <p>Population: ${feature.properties.population.toLocaleString()}</p>
        `
        )
        .addTo(map);
    }
  });

  map.on('mouseleave', 'states-layer', () => {
    map.getCanvas().style.cursor = '';
    popup.remove();
  });
});

step と interpolate の違い: 上記の例では、滑らかな色のグラデーションを使用するために interpolate を使っています。離散的な色の区分(例:「低/中/高」)には、代わりに ['step', ['get', 'population'], '#f0f0f0', 500000, '#fee0d2', 2000000, '#fc9272', 10000000, '#de2d26'] を使用します。データに自然なカテゴリがある場合や、境界値を厳密に扱う必要がある場合は、step を優先してください。

カラースケールの選び方:

// Linear interpolation (continuous scale)
'fill-color': [
  'interpolate',
  ['linear'],
  ['get', 'value'],
  0, '#ffffcc',
  25, '#78c679',
  50, '#31a354',
  100, '#006837'
]

// Step intervals (discrete buckets)
'fill-color': [
  'step',
  ['get', 'value'],
  '#ffffcc',  // Default color
  25, '#c7e9b4',
  50, '#7fcdbb',
  75, '#41b6c4',
  100, '#2c7fb8'
]

// Case-based (categorical data)
'fill-color': [
  'match',
  ['get', 'category'],
  'residential', '#ffd700',
  'commercial', '#ff6b6b',
  'industrial', '#4ecdc4',
  'park', '#45b7d1',
  '#cccccc'  // Default
]
ヒートマップ

最適な用途: ポイントの密度、イベントの位置、インシデントのクラスタリング

パターン: ポイントの密度を可視化します

map.on('load', () => {
  // Add data source (points)
  map.addSource('incidents', {
    type: 'geojson',
    data: {
      type: 'FeatureCollection',
      features: [
        {
          type: 'Feature',
          geometry: {
            type: 'Point',
            coordinates: [-122.4194, 37.7749]
          },
          properties: {
            intensity: 1
          }
        }
        // ... more points
      ]
    }
  });

  // Add heatmap layer
  map.addLayer({
    id: 'incidents-heat',
    type: 'heatmap',
    source: 'incidents',
    maxzoom: 15,
    paint: {
      // Increase weight based on intensity property
      'heatmap-weight': ['interpolate', ['linear'], ['get', 'intensity'], 0, 0, 6, 1],
      // Increase intensity as zoom level increases
      'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, 15, 3],
      // Color ramp for heatmap
      'heatmap-color': [
        'interpolate',
        ['linear'],
        ['heatmap-density'],
        0,
        'rgba(33,102,172,0)',
        0.2,
        'rgb(103,169,207)',
        0.4,
        'rgb(209,229,240)',
        0.6,
        'rgb(253,219,199)',
        0.8,
        'rgb(239,138,98)',
        1,
        'rgb(178,24,43)'
      ],
      // Adjust radius by zoom level
      'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, 15, 20],
      // Decrease opacity at higher zoom levels
      'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 15, 0]
    }
  });

  // Add circle layer for individual points at high zoom
  map.addLayer({
    id: 'incidents-point',
    type: 'circle',
    source: 'incidents',
    minzoom: 14,
    paint: {
      'circle-radius': ['interpolate', ['linear'], ['zoom'], 14, 4, 22, 30],
      'circle-color': '#ff4444',
      'circle-opacity': 0.8,
      'circle-stroke-color': '#fff',
      'circle-stroke-width': 1
    }
  });
});

ベストプラクティス

色のアクセシビリティ
// Use ColorBrewer scales for accessibility
// https://colorbrewer2.org/

// Good: Sequential (single hue)
const sequentialScale = ['#f0f9ff', '#bae4ff', '#7fcdff', '#0080ff', '#001f5c'];

// Good: Diverging (two hues)
const divergingScale = ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'];

// Good: Qualitative (distinct categories)
const qualitativeScale = ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'];

// Avoid: Red-green for color-blind accessibility
// Use: Blue-orange or purple-green instead
エラー処理
// Handle missing or invalid data
map.on('load', () => {
  map.addSource('data', {
    type: 'geojson',
    data: dataUrl
  });

  map.addLayer({
    id: 'data-viz',
    type: 'fill',
    source: 'data',
    paint: {
      'fill-color': [
        'case',
        ['has', 'value'], // Check if property exists
        ['interpolate', ['linear'], ['get', 'value'], 0, '#f0f0f0', 100, '#0080ff'],
        '#cccccc' // Default color for missing data
      ]
    }
  });

  // Handle map errors
  map.on('error', (e) => {
    console.error('Map error:', e.error);
  });
});

データサイズの目安

  • < 1 MB:GeoJSON をそのまま使用します
  • 1–10 MB:複雑さに応じて GeoJSON またはベクタータイルのどちらかを検討します
  • > 10 MB:ベクタータイルを使用します(Mapbox にタイルセットとしてアップロード)

実装の詳細については、references/performance.md を参照してください。

参考ファイル

可視化パターンの詳細を確認するには、該当する参考ファイルを読み込んでください。

  • references/clustering.md — ポイントのクラスタリング、カスタムクラスタープロパティ、クラスタリングとヒートマップの比較
  • references/3d-extrusions.md — 3D 建物押し出し、カスタムデータソース、データ駆動型の高さ
  • references/circles-lines.md — 円/バブルマップ、線データの可視化、交通流のスタイリング
  • references/animation.md — 時系列アニメーション、リアルタイムデータの更新、滑らかなトランジション
  • references/performance.md — ベクタータイルと GeoJSON の比較、フィーチャーステート、フィルタリング、段階的な読み込み
  • references/legends-use-cases.md — 凡例 UI、データインスペクター、データの前処理、選挙/COVID/不動産の例

リソース

コメント