100k points plot【Google Maps Platform & Deck.GL】(ひょうごの交通事故2017-2021)

↑画像をクリック 2017-2021兵庫県交通事故発生位置図

 兵庫県が2021年7月28日に公表したオープンデータの2017年~2021年の兵庫県における交通事故発生状況(発生年月日、時間帯、市区町、緯度・経度、天候、年齢、事故類型等)から、Google Maps Platformで作成した地図について、改良を重ねてきた。
 データが10万件を超えると読み込みに相当な時間を要することが懸案として残り、leafletにおけるLeafletpixiOverlayの検討を進めたが、データ読み込みや取り回しで納得できない状況が続いた。
 Google Maps PlatformのブログでMaps JavaScript API の機能に、deck.glWebGL オーバーレイ ビューとの統合が追加されたとの情報が提供され、Maps JavaScript APIで、deck.glに関するガイドサンプルを参考に、108,635件の可視化を試みた。

【データ整理】

  • Excelデータからcsvを経てQGISを用い、geojsonに変換。
  • 全データ108,635件中、2016年発生事故が247件含まれている。
  • 各年の死傷事故件数は、2016年:247件、2017年:26,738件、2018年:24,666件、2019年:22,891件、2020年:17,319件、2021年:16,774件。
  • 市区町データのうち、篠山市を丹波篠山市、豊岡町を豊岡市、養父町を養父市に修正。

【作業内容

  • 緯度経度に基づく事故地点のポイント表示
  • 死亡事故(赤)と負傷事故(青)のマーカー識別
  • マウスオーバー又はマウスクリックによる属性情報のTooltip表示
  • 県市区町のポリゴン表示
  • deck.glはReact Friendlyと紹介されているが、Maps JavaScript APIでは、Pure JavaScriptの例があることから、今回の作業は、Pure JavaScriptで行った
<html lang="ja">
    <head>
        <title>
            Hyogo Traffic Accidents 2017-2021 deck.gl ScatterplotLayer
        </title>

        <!-- deck.gl standalone bundle -->
        <script src="https://unpkg.com/deck.gl@^8.8.0/dist.min.js"></script>

        <!-- Google Maps dependencies -->
        <script src="https://maps.googleapis.com/maps/api/js?key=your_key&libraries=visualization&v=3.45"></script>

        <style type="text/css">
            body {
                margin: 0;
                padding: 0;
            }
            #map {
                width: 100vw;
                height: 100vh;
            }
            .deck-tooltip {
                font-family: Helvetica, Arial, sans-serif;
                padding: 6px !important;
                margin-top: -210px;
                margin-left: 10px;
                min-width: 270px;
                font-size: 12px;
            }
        </style>
    </head>

    <body>
        <div id="map"></div>
    </body>

    <script type="text/javascript">
        const map = new google.maps.Map(document.getElementById("map"), {
            center: { lat: 35.0, lng: 135.0 }, //Nishiwaki
            zoom: 9,
        });

        const INJURY_FILLCOLOR = [0, 255, 255]; //aqua
        const FATAL_FILLCOLOR = [255, 0, 0]; //red

        const INJURY_STROKECOLOR = [0, 0, 255]; //blue
        const FATAL_STROKECOLOR = [139, 0, 0]; //darkred

        const deckOverlay = new deck.GoogleMapsOverlay({
            layers: [
                new deck.GeoJsonLayer({
                    id: "polygon",
                    data: "../geojson/hyogo_areas021.geojson",
                    stroked: true,
                    filled: true,
                    getFillColor: [0,0,255,20],
                    getLineColor: [0,0,255,255],
                    lineWidthMinPixels: 1,
                }),

                new deck.ScatterplotLayer({
                    id: "point",
                    data: "../csv/hyogo_traffic_accident20211.json",
                    radiusScale: 2,
                    radiusMinPixels: 2,
                    stroked: true,
                    pickable: true,
                    autoHighlight: true,
                    getPosition: (d) => [
                        d["経度(東経)"],
                        d["緯度(北緯)"],
                        0,
                    ],
                    getFillColor: (d) =>
                        d["事故内容"] === "負傷" ? INJURY_FILLCOLOR : FATAL_FILLCOLOR,
                    getLineColor: (d) =>
                        d["事故内容"] === "負傷" ? INJURY_STROKECOLOR : FATAL_STROKECOLOR,
                    getLineWidth: (d) => 1,
                }),
            ],
            getTooltip: ({ object }) =>
                object &&
                `警察署:${object.警察署}
                番号:${object.番号}
                事故内容:${object.事故内容}
                死者数:${object.死者数}
                負傷者数:${object.負傷者数}
                路線コード:${object.路線コード}
                市区町:${object.市区町}
                発生年月日:${object.発生年月日}
                発生時間:${object.発生時間}
                昼夜:${object.昼夜}
                曜日:${object.曜日}
                天候:${object.天候}
                路面状態:${object.路面状態}
                道路形状:${object.道路形状}
                信号機:${object.信号機}
                道路線形:${object.道路線形}
                事故類型:${object.事故類型}
                年齢(当事者1):${object["年齢(当事者1)"]}
                年齢(当事者2):${object["年齢(当事者2)"]}
                当事者種別(当事者1):${object["当事者種別(当事者1)"]}
                当事者種別(当事者2):${object["当事者種別(当事者2)"]}
                中央分離施設:${object.中央分離施設}`,
        });

        deckOverlay.setMap(map);
    </script>
</html>

【出典】この地図は、以下の著作物を改変して利用しています。

  • 兵庫県オープンデータカタログページ 交通事故発生状況(掲載日2021年7月28日) [兵庫県企画部情報政策課]
    データ時点2021年4月1日、掲載日2021年7月28日とあるが、2021年12月31日のデータがあることからいずれも誤記の可能性がある。

【ご注意】地図メニューのGoogle関係の地図は、Google Maps Platformサービスの1日当たりのリクエスト、1分当たりのリクエスト及び1ユーザー1分当たりのリクエスト回数に制限を設けていますのでご了承ください。この場合、Gooogle Maps Platform版の利用も制限されます。 太平洋標準時0時にリセット[JST17時(夏時16時)]

コメント