行政区划相关信息在GIS中算是不可或缺的基础数据,然而由于行政区划经常会进行调整,所以许多网上搜集的已经存在了不同程度的过时。国外的数据,又会有领土的问题。DataV是阿里云出品的拖拽式可视化工具,专精于业务数据与地理信息融合的大数据可视化。阿里同时也提供的相应的GeoJSON数据供使用。
目录
GeoJSON简介
GeoJSON是一种基于JSON的地理空间数据交换格式,它定义了几种类型JSON对象以及它们组合在一起的方法,以表示有关地理要素、属性和它们的空间范围的数据。2015年,互联网工程任务组(IETF)与原始规范作者组建了一个GeoJSON工作组,一起规范GeoJSON标准。在2016年8月,推出了最新的GeoJSON数据格式标准规范(RFC 7946)。GeoJSON使用唯一地理坐标参考系统WGS1984和十进制度单位,一个GeoJSON对象可以是Geometry, Feature或者FeatureCollection.
其几何对象包括有点(表示地理位置)、线(表示街道、公路、边界)、多边形(表示国家、省、领土),以及由以上类型组合成的复合几何图形。TopoJSON基于GeoJSON作了扩展,使得文件更小。
基本几何图形:
类型 | 图形 | 数据 |
点 | { “type”: “Point”, “coordinates”: [30, 10] } |
|
线段 | { “type”: “LineString”, “coordinates”: [[30, 10], [10, 30], [40, 40]] } |
|
多边形 | { “type”: “Polygon”, “coordinates”: [[[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]]] } |
|
{ “type”: “Polygon”, “coordinates”: [ [[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]] ] } |
复合集合图形:
类型 | 图形 | 数据 |
点 | { “type”: “MultiPoint”, “coordinates”: [ [10, 40], [40, 30], [20, 20], [30, 10] ] } |
|
线段 | { “type”: “MultiLineString”, “coordinates”: [ [[10, 10], [20, 20], [10, 40]], [[40, 40], [30, 30], [40, 20], [30, 10]] ] } |
|
多边形 | { “type”: “MultiPolygon”, “coordinates”: [ [ [[30, 20], [45, 40], [10, 40], [30, 20]] ], [ [[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]] ] ] } |
|
{ “type”: “MultiPolygon”, “coordinates”: [ [ [[40, 40], [20, 45], [45, 30], [40, 40]] ], [ [[20, 35], [10, 30], [10, 10], [30, 5], [45, 20], [20, 35]], [[30, 20], [20, 15], [20, 25], [30, 20]] ] ] } |
GeoJson可通过geojson.io转换为shp、csv、kml等格式。
GeoJSON数据提取
使用GeoJSON行政区划边界提取小工具DataV.GeoAtlas,最低可以提取区县级边界数据,区域adcode可以查阅省市区adcode与经纬度映射表,提取方法如下。
- 省级:区域热力层默认显示为全国范围内,各个省和直辖市区域热力层数据,可以直接使用。
- 地市级:以提取浙江省范围内所有地级市边界数据为例,提取方法如下图所示。
- 区县级:以提取肇庆市范围内所有区县边界数据为例,提取方法如下图所示。
- 乡镇街道及自定义区域:乡镇街道数据需要用户自己获取。根据需要自定义区域边界,如中国大陆可以分为东部地区、西部地区、华南地区、华北地区、华中地区五大区,可以根据对应包含的省级边界数据合并得到。
Python抓取程序:
import requests import os def get_json(save_dir, adcode): # 获取当前地图轮廓 base_url = 'https://geo.datav.aliyun.com/areas/bound/' + str(adcode) + '.json' full_url = 'https://geo.datav.aliyun.com/areas/bound/' + str(adcode) + '_full.json' base_r = requests.get(base_url) if base_r.status_code == 200: cur_obj_name = base_r.json()['features'][0]['properties']['name'] print(cur_obj_name) cur_file_dir = os.path.join(save_dir, cur_obj_name) if not os.path.exists(cur_file_dir): os.mkdir(cur_file_dir) base_json_file = os.path.join(cur_file_dir, str(adcode) + '.json') with open(base_json_file, 'w') as file: file.write(base_r.text) # 获取当前地图子地图轮廓 full_r = requests.get(full_url) if full_r.status_code == 200 and 'cur_obj_name' in vars(): full_json_file = os.path.join(cur_file_dir, str(adcode) + '_full.json') with open(full_json_file, 'w') as file: file.write(full_r.text) for item in full_r.json()['features']: chadcode = item['properties']['adcode'] if chadcode == adcode: pass else: get_json(cur_file_dir, chadcode) if __name__ == "__main__": get_json('D:\\DataV', 100000)
在GeoPandas中使用GeoJson数据
绘制含有九段线的中国地图:
import geopandas as gpd import matplotlib.pyplot as plt gdf = gpd.read_file("100000_full.json",encoding='utf-8') gdf.plot() plt.show()
如果出现如下错误:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-13-6be42f4feb94> in <module> ----> 1 gdf = gpd.read_file("100000_full.json",encoding='gbk') 2 gdf.plot() 3 plt.show() D:\ProgramData\Anaconda3\lib\site-packages\geopandas\io\file.py in read_file(filename, bbox, **kwargs) 93 94 columns = list(features.meta["schema"]["properties"]) + ["geometry"] ---> 95 gdf = GeoDataFrame.from_features(f_filt, crs=crs, columns=columns) 96 97 return gdf D:\ProgramData\Anaconda3\lib\site-packages\geopandas\geodataframe.py in from_features(cls, features, crs, columns) 281 282 rows = [] --> 283 for f in features_lst: 284 if hasattr(f, "__geo_interface__"): 285 f = f.__geo_interface__ fiona/ogrext.pyx in fiona.ogrext.Iterator.__next__() fiona/ogrext.pyx in fiona.ogrext.FeatureBuilder.build() TypeError: startswith first arg must be bytes or a tuple of bytes, not str
导致原因是Windows环境下,文件被保存为ANSI编码了,解决方案是将其修改为UTF-8编码。
其他链接:
- https://lbs.amap.com/api/javascript-api/example/district-search/draw-district-boundaries/
- http://lbsyun.baidu.com/jsdemo.htm#c1_10
- https://lbs.amap.com/api/javascript-api/guide/services/district-search
- https://gallery.echartsjs.com/editor.html?c=xr1IEt3r4Q