添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
初探地理数据可视化工具 kepler.gl

初探地理数据可视化工具 kepler.gl

1. 写在前面

最近在看 Ubur 的 Deck.gl ,间接性接触到它们开源的一个地理数据分析可视化工具 kepler.gl ,之前也有看到,没有怎么玩过,恰好最近有点时间,来玩一玩这个地理数据可视化工具。

下面就以探索的方式展开简单玩玩 kepler.gl

1.1 开源可视化库

可能工作的原因可能比较熟悉地理相关库,这里就举例经常看到用到的一些开源可视化库与工具。

1.1.1 简单分类

图表库

地理库

数据驱动框架

渲染库

1.1.2 简单关系图

1.2 kepler.gl 了解

kepler.gl 是 Uber 开源,面向大规模数据集的强大开源地理数据分析工具,基于 deck.gl 构建的 React 组件,高性能,用于大规模地理数据集的可视化分析探索。
--- kepler.gl

提到 deck.gl 就自然要了解一下地理空间可视化框架 Vis.gl 生态

  • deck.gl - A high-performance WebGL 2 rendering framework for big data visualizations that integrates perfectly with reactive applications.
  • react-map-gl - A React wrapper around Mapbox GL which works seamlessly with deck.gl.
  • React-vis - A composable, deeply customizable charting library
  • luma.gl - A comprehensive set of WebGL 2 components targeting high-performance rendering and GPGPU computing.
  • loaders.gl - a suite of framework-independent loaders for file formats focused on visualization of big data, including point clouds, 3D geometries, images, geospatial formats as well as tabular data.
  • nebula.gl - High-Performance, 3D-enabled GeoJSON editing deck.gl and React

了解大致关系情况后,就搭建 kepler.gl,来玩一玩看看。

2. 搭建 kepler.gl

2.1 生成项目、安装依赖

生成项目使用 create-react-app 脚手架工具

npx create-react-app kepler.gl-taste
cd kepler.gl-taste

安装 kepler.gl 相关依赖, kepler.gl 使用 Redux 管理组件状态,这里需要安装 redux, react-redux

npm install --save kepler.gl redux react-redux react-virtualized styled-components

安装 react-virtualized 需要使用到 AutoSizer 组件,方便自动调整适配屏幕

2.2 添加相关代码

使用 Redux 创建状态管理 store.js

import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import keplerGlReducer from "kepler.gl/reducers";
import { enhanceReduxMiddleware } from "kepler.gl/middleware";
const initialState = {};
const customizedKeplerGlReducer = keplerGlReducer.initialState({
    // TODO: customize initial state
const reducers = combineReducers({
  keplerGl: customizedKeplerGlReducer,
    // TODO: app reducer
  // app: appReducer
export const middlewares = enhanceReduxMiddleware([
  // Add other middlewares here
export const enhancers = [applyMiddleware(...middlewares)];
// using createStore
export default createStore(reducers, initialState, compose(...enhancers));

挂载 KeplerGl 组件 app.js

import AutoSizer from "react-virtualized/dist/commonjs/AutoSizer";
import KeplerGl from "kepler.gl";
import "./App.css";
const MAPBOX_TOKEN = process.env.REACT_APP_MAPBOX_TOKEN; // eslint-disable-line
const MAPBOX_API_URL = "https://api.mapbox.com";
function App() {
  return (
    <div className="App">
      <AutoSizer>
        {({ height, width }) => (
          <KeplerGl
            mapboxApiAccessToken={MAPBOX_TOKEN}
            id="map"
            width={width}
            height={height}
            mapboxApiUrl={MAPBOX_API_URL}
      </AutoSizer>
export default App;

挂载 APP 组件,注入 store, index.js

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./store";
import App from "./App";
import "./index.css";
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")

更多相关代码查看 kepler.gl-taste

2.3 部署

之前一般选择 Vercel 与 travis-ci 来持续集成部署,现在 Github Actions 也比较好用了,这里就使用 Github Actions 来做持续集成。

新建工作流,配置 Actions deploy-gh-page.yml

name: deploy gh-pag CI
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.x]
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm install
    - run: npm run build
    - name: deploy
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.ACCESS_TOKEN }}
        publish_dir: ./build

部署完成之后,访问部署后的 地址 ,下就开始来玩玩 kepler.gl

3. 使用 kepler.gl

3.1 拾取要分析的数据

这里就以带地理信息的天气数据来玩玩 kepler.gl 看看效果,数据就使用 国家气象科学数据中心 收集的地面站点数据。不过使用数据之前需要注册帐号,审核通过之后就可以使用了。

这里就以四川地面气象站逐小时观测资料为演示数据,选取要观测要素,数据检索完成后,申请数据下载。

审核通过后下载数据,数据格式如下图所示:

可以看到数据只要站点编号,缺少站点信息数据,再次下载站点数据,数据格式如下图所示:

下面进行数据合并处理

3.2 处理数据

编写 JS 脚本处理两个 CSV 数据格式,将只要站点编号的文件注入站点信息,为了方便处理这里导出为 Json 文件。

const fs = require("fs")
const parseToJson = (data) => {
    const lines = data.trim().split(/[\r?\n]{1,2}/)
    const rows = lines.map((line) => line.trim().split(','))
    const headRow = rows.slice(0, 1)[0]
  const bodyRows = rows.slice(1)
  const headMap = headRow.reduce((pre, cur, index) => {
      pre.set(index, cur)
      return pre
    }, new Map())
  const records = bodyRows.map((row) => {
      const initialValue = {}
      const record = row.reduce((pre, cur, index) => {
        const key = headMap.get(index)
        if (key) {
          const vaule = Number(cur)
          if (cur === '' || Number.isNaN(vaule)) {
            pre[key] = cur
          } else {
            pre[key] = vaule
        return pre
      }, initialValue)
      return record
  return records
const Station_Id_C = fs.readFileSync('./Station_Id_C.csv').toString();
const SrouceData = fs.readFileSync('./SrouceData.csv').toString();
const srouceData = parseToJson(SrouceData)
const stationJson = parseToJson(Station_Id_C)
const stationMap = new Map()
for (item of stationJson) {
        stationMap.set(item.Station_Id_C, item)
for (item of srouceData) {
    const station = stationMap.get(item.Station_Id_C)
    item.Lat = station.Lat
    item.Lon = station.Lon