2018年度駅別乗降客数データをdeck.glで可視化してみました

# はじめに
- 国土数値情報の[2018年度駅別乗降客数データ](https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-S12-v2_6.html)を、[deck.gl](https://deck.gl/)の[ScatterplotLayer](https://deck.gl/docs/api-reference/layers/scatterplot-layer)を用いて可視化してみました。

- [2018年度駅別乗降客数データ](https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-S12-v2_6.html)は以下の国土数値情報の提供サイトよりシェープファイル（ライン）がダウンロードできます。
※本記事では、シェープファイル（ライン）をQGISで重心（ポイント）に変換したデータを用いています。
https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-S12-v2_6.html

- 背景地図には[Mapbox](https://www.mapbox.com/)を使用しているため、Mapboxにてアクセストークンの取得が必要になります。

# アウトプットイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/3480fe47-768f-61dc-63eb-59e0df64fb07.png)

![bandicam-2021-01-25-21-01-10-979.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/f632ceb9-5804-d02a-3330-cae3e2482bbb.gif)

※「駅別乗降客数データ」(国土交通省) 
(https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-S12-v2_6.html) を加工して作成

# 前提条件
- 駅別乗降客数データは以下のデータ形式（csvファイル）とします。
- 最後列の「S12_037」が2018年度の駅別乗降客数になります。
- 表示の都合上、一部のデータは削除しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/e6de2788-7d6b-4374-bb77-490694f8eae1.png)

- 鉄道路線や鉄道駅のラインデータは[国土数値情報](https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N02-v2_3.html)からダウンロードし、geojsonファイルを用いています。
- なお、駅別乗降客数データや鉄道路線や鉄道駅のラインデータはWebサーバ上に保存されていることが前提です。

# html
```html:2018NumberOfPassengers.html
<html>
  <head>
    <title>2018年駅別乗降客数データ（国土数値情報）</title>
    <meta charset="UTF-8">
    <script src="https://unpkg.com/deck.gl@^7.0.0/dist.min.js"></script>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.js"></script>
    <link rel="stylesheet" href="style.css"/>
  </head>
  <body>
    <div id="control-panel">
      <div>
        <label>opacity</label>
        <input id="opacity" type="range" min="0" max="1" step="0.01" value="0.5"></input>
        <span id="opacity-value"></span>
      </div>
    </div>
    <script  src="script.js"></script>
  </body>
</html>

```
# CSS
```css:style.css
html,body {
  font-family: Helvetica, Arial, sans-serif;
  width: 100vw;
  height: 100vh;
  margin: 0;
}
.deck-tooltip {
  font-family: Helvetica, Arial, sans-serif;
  padding: 6px !important;
  margin: 8px;
  color: #ffffff;
  background-color: #4682b4;
  max-width: 300px;
  font-size: 20px;
}

#control-panel {
  position: absolute;
  top: 0;
  left: 0;
  margin: 12px;
  padding: 20px;
  font-size: 12px;
  line-height: 1.5;
  z-index: 1;
  background: #fff;
  font-family: Helvetica, Arial, sans-serif;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
}

label {
  display: inline-block;
  width: 140px;
}
```
#JavaScript
- mapboxApiAccessTokenには、取得したアクセストークンを入力してください。
- S12-19_NumberOfPassengers_point_2018.csvが駅別乗降客数データになります。
- N02-19_RailroadSection.geojsonが鉄道路線のラインデータになります。
- N02-19_Station.geojsonが鉄道駅のラインデータになります。

```javascript:script.js
const deckgl = new deck.DeckGL({
  mapboxApiAccessToken: 'アクセストークンを入力してください',
  mapStyle: 'mapbox://styles/mapbox/dark-v9',
  initialViewState: {
    latitude: 35.685175,
    longitude: 139.7527995,
    zoom: 10,
    maxZoom: 20,
    pitch: 45,
    bearing: 15
  },
  controller: true,
  });

const OPTIONS = ['opacity'];

const data = d3.csv('data/S12-19_NumberOfPassengers_point_2018.csv');
const railway = d3.json('data/N02-19_RailroadSection.geojson');
const station = d3.json('data/N02-19_Station.geojson');

const renderLayer = () => {
    const options = {};
    OPTIONS.forEach(key => {
      const value = document.getElementById(key).value;
      document.getElementById(key + '-value').innerHTML = value;
      options[key] = Number(value);
    });
    
    const geoJsonLayer1 = new deck.GeoJsonLayer({
      id: 'railway',
      data: railway,
      stroked: false,
      filled: false,
      lineWidthMinPixels: 2,
      parameters: {
        depthTest: false
      },
      opacity: 0.7,
      getLineColor: [240,240,240],
      getLineWidth: 2,
    
      pickable: false,
    });
    
    const geoJsonLayer2 = new deck.GeoJsonLayer({
      id: 'station',
      data: station,
      stroked: false,
      filled: false,
      lineWidthMinPixels: 2,
      parameters: {
        depthTest: false
      },
      opacity: 1,
      getLineColor: [229,229,229],
      getLineWidth: 10,
    
      pickable: false,
    });

    const scatterplotLayer = new ScatterplotLayer({
      id: 'scatter-plot',
      data: data,
      radiusUnits: 'meters',
      radiusScale: 1,
      lineWidthUnits: 'meters',
      lineWidthScale: 1,
      stroked: false,
      filled: true,
      pickable: true,
      opacity: 0.5,
      radiusMinPixels: 4,
      radiusMaxPixels: 100,
      lineWidthMinPixels: 1,
      getPosition: d => [Number(d.lng), Number(d.lat)],
      getRadius: d => Math.sqrt(d.S12_037),
      getColor: d => [101, 101, 255],
      getLineColor: d => [0, 0, 0],
      ...options
    });

 deckgl.setProps({
  layers:[geoJsonLayer1, geoJsonLayer2, scatterplotLayer],
  getTooltip: ({object}) => object && `${object.S12_002}\n${object.S12_003}\n${object.S12_001}駅\n駅別乗降客数: ${object.S12_037}`
});

}

renderLayer();

OPTIONS.forEach(key => {
  document.getElementById(key).oninput = renderLayer;
});
```
# 参考文献
https://deck.gl/docs/api-reference/layers/scatterplot-layer
https://deck.gl/gallery/
https://github.com/visgl/deck.gl
https://deckgl.readthedocs.io/en/latest/index.html