kepler.gl简介
Kepler.gl是一个开源的地理空间数据可视化工具,由Uber开发并开源。它旨在帮助用户快速、直观地探索和展示大型地理空间数据集。
主要特点
- 用户友好界面,提供了一个直观的界面,使用户能够轻松上传数据、选择图层类型、调整可视化参数等。无需编程背景的用户也能快速上手。
- 多图层支持,允许用户在同一个地图上添加多个图层,包括散点图、热力图、轨迹图、柱状图、栅格图等。每个图层可以独立配置,给用户提供了高度的灵活性。
- 大数据处理,该工具能够处理大型数据集,支持数百万条数据记录的实时渲染。利用WebGL技术,gl能够高效地处理和显示复杂的数据。
- 数据兼容性,支持多种数据格式,包括CSV、GeoJSON、JSON等。用户可以直接将这些文件拖放到界面中进行可视化。
- 交互功能,提供了丰富的交互功能,包括缩放、平移、选择、过滤等,使用户能够深入探索数据。
- 自定义样式,用户可以自定义地图的样式、颜色、标记等,以便更好地展示数据和突出重点。
- 导出功能,支持将生成的地图导出为图像或HTML文件,方便分享和嵌入到其他网页中。
技术架构
Kepler.gl是一个强大的开源地理空间分析工具,用于大规模数据集的可视化。它由Uber的数据可视化团队开发,并且是基于Web技术构建的。Kepler.gl涉及到以下几个主要技术领域:
- WebGL: Kepler.gl通过WebGL进行渲染,这是一种在不需要插件的情况下在网页浏览器中使用GPU加速图形的技术。
- React: Kepler.gl是用React构建的,这是一个用于构建用户界面的JavaScript库,特别适合构建大型应用程序,其中数据随时间变化。
- Redux: 这是一个用于JavaScript应用程序状态管理的库。gl使用Redux来管理其应用程序状态,包括地图状态、数据和用户交互。
- Mapbox GL JS: Kepler.gl使用Mapbox GL JS来处理地图的底层渲染,这是一个基于WebGL的JavaScript库,用于渲染交互式地图。
- gl: deck.gl是一个WebGL-powered数据可视化框架,专为探索和可视化数据而设计。Kepler.gl使用deck.gl来创建复杂的地理空间可视化效果。
- js: d3.js是一个JavaScript库,用于使用HTML, SVG, 和CSS操作文档。Kepler.gl可能会使用d3.js来执行某些数据处理任务或者绘制定制的图表和图形。
- js和npm: Kepler.gl的开发环境可能涉及到Node.js(一个基于Chrome V8引擎的JavaScript运行时),以及npm(Node.js的包管理器),用于管理项目依赖。
- GeoJSON和其他地理数据格式: Kepler.gl支持多种地理数据格式,包括GeoJSON,这是一种基于JSON的地理数据交换格式。
- 其他数据处理和分析库: Kepler.gl为了处理和分析地理数据,可能会用到其他的JavaScript库和工具,比如js等。
- CSS和HTML: 用于定义gl用户界面的样式和结构。
kepler.gl在Anaconda中的安装
kepler.gl的Python环境的安装属实不容易,这个不容易主要是由于环境版本的影响导致的。虽然的官方的提供了Jupyter Notebook的章节,但是实际上并没有什么用。以下是个人研究了2天后暂时摸索出来的算是半可能的方案。
如果使用的是最新版本的Andaconda(Anaconda3-2024.06-1-Linux-x86_64.sh),先按如下步骤安装:
conda install -c conda-forge nodejs conda install -c conda-forge keplergl
能够顺利安装,但是运行以下测试代码:
from keplergl import KeplerGl map_1 = KeplerGl(height=600) map_1
给出的结果是:
UserGuide: https://docs.kepler.gl/docs/keplergl-jupyter Loading widget...
查询环境:!jupyter –version
Selected Jupyter core packages... IPython: 8.25.0 ipykernel: 6.28.0 ipywidgets: 7.7.2 jupyter_client: 8.6.0 jupyter_core: 5.7.2 jupyter_server: 2.14.1 jupyterlab: 4.2.3 nbclient: 0.8.0 nbconvert: 7.10.0 nbformat: 5.9.2 notebook: 7.2.1 qtconsole: 5.5.1 traitlets: 5.14.3
查看安装的拓展:!jupyter labextension list
JupyterLab v4.2.3 /home/biaodianfu/anaconda3/share/jupyter/labextensions keplergl-jupyter v0.3.2 enabled X jupyterlab-plotly v5.22.0 enabled X @pyviz/jupyterlab_pyviz v3.0.2 enabled OK @jupyter-notebook/lab-extension v7.2.1 enabled OK @jupyter-widgets/jupyterlab-manager v3.1.8 enabled X (python, jupyterlab_widgets) The following extensions may be outdated or specify dependencies that are incompatible with the current version of jupyterlab: keplergl-jupyter jupyterlab-plotly @jupyter-widgets/jupyterlab-manager If you are a user, check if an update is available for these packages. If you are a developer, re-run with `--verbose` flag for more details. Other labextensions (built into JupyterLab) app dir: /home/biaodianfu/anaconda3/share/jupyter/lab
发现部分扩展的版本与当前的jupyterlab不匹配,可能需要针对jupyterlab降级,其实也并没有成功。但是根据网上教程,使用以下代码能正常显示。
from keplergl import KeplerGl import base64 import IPython test_map = KeplerGl(height=600) orig_html = str(test_map._repr_html_(), 'utf-8') better_html = orig_html b64 = base64.b64encode(better_html.encode('utf-8')) src = f"data:text/html;base64,{b64.decode('utf-8')}" base64d_html = f'<iframe src="{src}" style="width:95%;height:600px">' IPython.display.HTML(base64d_html)
改用用jupyter notebook,具体表现与jupyter lab基本保持一致。
查询资料说是使用ipywidgets 7.8.0和widgetsnbextension 3.6.5可行。
pip install ipywidgets==7.8.0 pip install widgetsnbextension==3.6.5 pip install jupyter_contrib_nbextensions
执行完后还是无法正常显示。由于无法解决上面的问题,尝试使用创建虚拟环境的方式进行。
conda create -n keplergl python=3.7 conda activate keplergl pip install geopandas jupyterlab keplergl rtree conda search nodejs conda install -c conda-forge nodejs npm config set registry http://registry.npmjs.org/ jupyter labextension install @jupyter-widgets/jupyterlab-manager keplergl-jupyter
执行过程中报如下错误:
jupyter labextension install @jupyter-widgets/jupyterlab-manager keplergl-jupyter (Deprecated) Installing extensions with the jupyter labextension install command is now deprecated and will be removed in a future major version of JupyterLab. Users should manage prebuilt extensions with package managers like pip and conda, and extension authors are encouraged to distribute their extensions as prebuilt packages Building jupyterlab assets (production, minimized) An error occurred. RuntimeError: JupyterLab failed to build See the log file for details: /tmp/jupyterlab-debug-3hrezi9i.log
清理和重新构建JupyterLab:
jupyter lab clean jupyter lab build jupyter nbextension install --py --sys-prefix keplergl # can be skipped for notebook 5.3 and above jupyter nbextension enable --py --sys-prefix keplergl # can be skipped for notebook 5.3 and above pip install ipywidgets==7.8.0 pip install widgetsnbextension==3.6.5 pip install jupyter_contrib_nbextensions jupyter labextension list JupyterLab v3.6.7 /home/biaodianfu/anaconda3/envs/keplergl/share/jupyter/labextensions jupyterlab_pygments v0.2.2 enabled OK (python, jupyterlab_pygments) keplergl-jupyter v0.3.2 enabled OK @jupyter-widgets/jupyterlab-manager v3.1.8 enabled OK (python, jupyterlab_widgets) Other labextensions (built into JupyterLab) app dir: /home/biaodianfu/anaconda3/envs/keplergl/share/jupyter/lab The following source extensions are overshadowed by older prebuilt extensions: @jupyter-widgets/jupyterlab-manager pip install ipywidgets==7.8.0 pip install widgetsnbextension==3.6.5 pip install jupyter_contrib_nbextensions
完成后打开Jupyter notebook已经能够正常使用了。但Jupyter Lab还是不可以。如果你找到了更好的解决方案,感谢告知!
kepler.gl的使用
虽然Kepler.gl最初是为JavaScript和Web环境设计的,但它也有一个方便的Python接口,允许Python用户轻松地创建和嵌入Kepler.gl地图。
加载Kepler.gl地图
Kepler.gl的Python接口主要通过KeplerGl类来使用。以下是一个简单的示例,展示如何创建和显示一个地图。
from keplergl import KeplerGl import pandas as pd data = { 'lat': [37.7749, 34.0522, 40.7128], 'lon': [-122.4194, -118.2437, -74.0060], 'city': ['San Francisco', 'Los Angeles', 'New York'] } df = pd.DataFrame(data) # 初始化KeplerGl地图 map_1 = KeplerGl(height=400) # 添加数据到地图 map_1.add_data(data=df, name="Cities") # 显示地图 map_1
KeplerGl()的参数
- height:int型,展示的地图窗体的高度,默认为400px
- data:dict型,传入地图中的字典型数据集
- use_arrow:布尔值,允许使用GeoArrow更快地加载和渲染数据,默认:False
- config:dict型,地图参数配置信息
- show_docs:bool型,设置是否显示用户指引文档的地址,默认为True,即显示
添加数据集
add_data()的参数
- data:传入地图中的数据集,可以是CSV, GeoJSON, DataFrame
- name:数据集传入图层中显示的名称
加载地理数据文件kepler.gl 支持 4 种数据格式,分别是:CSV, GeoJSON, DataFrame, GeoDataFrame. 其中部分地理数据可视化类型只支持 GeoJSON 格式的数据。
kepler.gl 会对 csv 格式的文件的字段类型进行推断,因此一定要在代表经纬度信息的字段名称中加上对应的 lat、lng 部分,格式有三种:
- <name>_lat, <name>_lng
- <name>_lat, <name>_lon
- <name>_latitude, <name>_longitude
其中 <name> 是自选的变量名称。若不按此格式命名经纬度字段名称,导入数据后不能自动识别为可能的图形对象,需要手动进行选择。
添加多个数据集
data_1 = { 'lat': [37.7749, 34.0522], 'lon': [-122.4194, -118.2437], 'city': ['San Francisco', 'Los Angeles'] } data_2 = { 'lat': [40.7128], 'lon': [-74.0060], 'city': ['New York'] } df_1 = pd.DataFrame(data_1) df_2 = pd.DataFrame(data_2) map_3 = KeplerGl(height=400) map_3.add_data(data=df_1, name="California Cities") map_3.add_data(data=df_2, name="New York City") map_3
自定义可视化配置
与 pyecharts, matplotlib, folium 等可视化库的配置方式不同,在 kepler.gl 中不需要编写颜色、图标、样式、触发事件等参数配置代码,只需要在页面上的功能面板中进行可视化配置操作即可,配置的参数可以复用,真正实现低代码的使用方式。
Kepler.gl 设置项分为 4 个工具栏,左其分别是 Layers(图层)、Filters(过滤)、Interaction(交互)、Basemap(底层地图)。
四者的作用可以概括为:
- Layers(图层):数据展示的图层,位于底层地图上面。就是我们导入的数据后,控制样式的图层。
- Filters(过滤器):用以过滤数据。例如,上图中时间轴就是一个过滤器,用以过滤时间段,显示相同时间段的数据。
- Interaction(交互):即鼠标移动时显示的数据信息。
- Basemap(底层地图):就是最底层地图样式。有 4 种样式可选。
Layers(图层)功能
数据展示的图层,位于底层地图图层之上。用以设置导入数据后,数据图层显示的样式。多套数据可通过图层叠加显示,也可以自行创建新图层。
数据图层有多达 40+ 种配色方案可供选择(每种配色方案会根据所选择的 steps 数量进行相应调整),也可以自定义配置;可设置配色的基准字段(这里设置为 region)、透明度:
可针对每个数据图层配置其可视化的类型,不同类型可设置的内容不尽相同。例如标点型可以设置标记点半径大小、轮廓线条颜色等;路径型可以设置路径线条粗细、海拔比例等:
Arc 和 Line 路径型可视化可在地图上显示路径信息,前提是需要有两组经纬度坐标数据,即起点坐标和终点坐标:
部分可视化类型(如 Hexbin, Cluster)还可以通过高度(海拔)数据,绘制出 3D 数据地图:
Filters(过滤器)功能
用以过滤图层中的数据。
数值型数据,可选择数值范围;字符串型数据,可通过选择对应值筛选;时间型数据,可添加时间轴,配合路径信息,还可以实现时间轮播路径动画。
Interaction(交互)功能
设置触发事件的交互数据信息。
可设置悬停在目标上显示的数据信息内容,设置是否显示经纬度坐标信息,设置是否允许通过地理编码器进行地点搜索等。
Basemap(底图)功能
设置底层地图样式及底层地图的图层顺序和图层内容。可设置地图图层的显示内容及顺序。另外 3D 地图还可以设置建筑物的颜色。
保存和加载地图配置
.config
你可以使用 .config 打印当前地图的配置。
map_1.config
输出示例:
## {u'config': {u'mapState': {u'bearing': 2.6192893401015205, # u'dragRotate': True, # u'isSplit': False, # u'latitude': 37.76209132041332, # u'longitude': -122.42590232651203,
将配置应用到地图
config = { 'version': 'v1', 'config': { 'mapState': { 'latitude': 37.76209132041332, 'longitude': -122.42590232651203, 'zoom': 12.32053899007826 } ... } } map_1.add_data(data = df, name = 'data_1') map_1.config = config
或在创建地图时加载配置:
map_1 = KeplerGl(height = 400, data = {'data_1': my_df}, config = config)
保存地图
.save_to_html()方法
输入参数:
- data(可选):一个数据字典{“name”: data},如果不提供,则使用当前地图数据。
- config(可选):地图配置字典,如果不提供,则使用当前地图配置。
- file_name(可选):HTML文件名,默认为html。
- read_only(可选):如果read_only设置为True,则隐藏侧边面板以禁用地图自定义功能。
你可以将当前地图导出为交互式的HTML文件。
# 这将保存当前地图 map_1.save_to_html(file_name = 'first_map.html') # 这将保存带有提供的数据和配置的地图 map_1.save_to_html(data = {'data_1': df}, config = config, file_name = 'first_map.html') # 这将保存一个禁用交互面板的地图 map_1.save_to_html(file_name = 'first_map.html', read_only = True)
_repr_html_()方法
_repr_html_()方法,使得将kepler.gl与flask等进行结合更加方面,就像folium中的_repr_html_()方法一样。
输入参数:
- data(可选):一个数据字典{“name”: data},如果不提供,则使用当前地图数据。
- config(可选):地图配置字典,如果不提供,则使用当前地图配置。
- read_only(可选):如果read_only设置为True,则隐藏侧边面板以禁用地图自定义功能。
结合flask:
from flask import Flask from keplergl import KeplerGl app = Flask(__name__) @app.route('/') def index(): map_1 = KeplerGl() return map_1._repr_html_() if __name__ == '__main__': app.run(debug = True)
而如果你对dash有所了解,那么纯Python快速开发出一个嵌入kepler.gl的交互式web应用将会变得非常容易,就像下面这个简单的例子一样:
import dash from keplergl import KeplerGl import dash_html_components as html import dash_core_components as dcc from dash.dependencies import Input, Output import requests app = dash.Dash(__name__) app.layout = html.Div([ html.H1("Dash结合Kepler.gl:"), dcc.Dropdown( id = 'demo-dropdown', options = [ {'label': '重庆', 'value': '重庆'} ], style = {'width': '300px'} ), html.Iframe( id = 'iframe', style = {'height': '800px', 'width': '1900px'} ) ]) @app.callback( Output('iframe', 'srcDoc'), [Input('demo-dropdown', 'value')] ) def switch_area(selected_area): if selected_area == '重庆': map_1 = KeplerGl( data = { selected_area: requests.get('https://geo.datav.aliyun.com/areas_v2/bound/500000_full.json').json() }, config = { "mapState": { "bearing": 0, "dragRotate": False, "latitude": 29.751819, "longitude": 107.441431, "pitch": 0, "zoom": 6, "isSplit": False } }) return map_1._repr_html_().decode() else: map_1 = KeplerGl( data = { selected_area: requests.get('https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json').json() }, config = { "mapState": { "bearing": 0, "dragRotate": False, "latitude": 29.751819, "longitude": 107.441431, "pitch": 0, "zoom": 3, "isSplit": False } }) return map_1._repr_html_().decode() if __name__ == '__main__': app.run_server()
参考链接:
以前用的时候感觉很顺利,现在重新装结果各种错!
折腾了两天,按照博主的文章成果了!感谢干货