数据, 术→技巧

中国行政区划边界GeoJSON数据

钱魏Way · · 7,886 次浏览
!文章内容如有错误或排版问题,请提交反馈,非常感谢!

行政区划相关信息在GIS中算是不可或缺的基础数据,然而由于行政区划经常会进行调整,所以许多网上搜集的已经存在了不同程度的过时。国外的数据,又会有领土的问题。DataV是阿里云出品的拖拽式可视化工具,专精于业务数据与地理信息融合的大数据可视化。阿里同时也提供的相应的GeoJSON数据供使用。

GeoJSON简介

GeoJSON是一种基于JSON的地理空间数据交换格式,它定义了几种类型JSON对象以及它们组合在一起的方法,以表示有关地理要素、属性和它们的空间范围的数据。2015年,互联网工程任务组(IETF)与原始规范作者组建了一个GeoJSON工作组,一起规范GeoJSON标准。在2016年8月,推出了最新的GeoJSON数据格式标准规范(RFC7946)。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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注