【Python+ArcGIS】数据分析实战——静安教育资源数据获取、处理及空间可视化分析

本文介绍了如何使用八爪鱼采集器获取静安区教育资源数据,然后结合Python、百度地图API和ArcGIS进行地理编码、坐标转换及空间可视化分析。通过创建自定义工具,实现了从BD09LL到WGS84坐标的转换,并在ArcGIS中展示了不同坐标系下的学校分布。最终,分析了静安区教育资源的空间分布特征。
摘要由CSDN通过智能技术生成

【Python + ArcGIS】数据分析实战

——静安教育资源数据获取、处理及空间可视化分析

0 前言

最近,由于科研需要,基于 百度地图APIGitHub wandergis 提供的开源源码,面向对象,自主设计地理编码和坐标转换工具。基于此,本文以静安教育资源数据获取、处理及空间可视化分析为例,结合爬虫与GIS,介绍地理数据获取、处理及可视化分析的实现方法。
由于本人对于爬虫不甚擅长,因此借用了现成的工具(八爪鱼采集器)进行数据爬取。

1 数据需求

1.1 数据内容

本文基于静安门户网站数据所提供的“学校名称”、“学校地址”等信息进行数据获取、处理及空间可视化分析。

学-便民直通车-公共服务 -上海静安门户网站欢迎您!
在这里插入图片描述

1.2 分析需求

  1. 利用爬虫工具获取静安门户网站教育数据,分析数据结构,并简要分析数据结果
  2. 利用基于 百度地图APIGitHub wandergis 自主设计的地理编码和坐标转换工具进行地理编码与坐标转换
  3. 利用ArcGIS进行数据可视化分析

2 工具准备

  1. 八爪鱼采集器
  2. Microsoft Office Excel
  3. Python
    涉及的库:requests, urllib, pandas, math, os
  4. 百度地图API
  5. ArcGIS

3 数据处理流程

数据处理
Python 库
分析数据格式
数据爬取
地理编码
坐标转换
数据可视化分析
request,surllib 用于网络
pandas,math 用于数据处理
os 用于文件操作
工具准备
八爪鱼采集器
Microsoft Office Excel
Python
ArcGIS
百度地图API
天地图上海 ArcGIS服务
数据需求
需求达成

4 数据处理

4.1 数据爬取与数据格式分析

由于本人对于爬虫不甚擅长,通过利用八爪鱼采集器,导入网页地址(学-便民直通车-公共服务 -上海静安门户网站欢迎您!http://www.jingan.gov.cn/ggfw/004014/004014008/bmztcmoreinfo.html),通过自动识别网页生成采集流程并加以修改,采集网页数据并导出。
在这里插入图片描述
导出结果如下:
在这里插入图片描述
数据与数据类型:

数据表头实际含义数据类型实际利用
标题学校名称字符串空间可视化
标题链接链接地址字符串
bmdz学校地址字符串地理编码
编号电话字符串

根据分析需求,对学校数据进行整理,并新增“学校类型”这一属性(字符串及各级各类学校二元表),形成如下表格:
在这里插入图片描述
经个人统计,静安区共有各级各类学校210所(含分校),详细类别如下:
在这里插入图片描述

4.2 地理编码与坐标转换

对于“学校地址”这一字符串类型的数据,无法通过直接的方法进行空间数据可视化,必须先通过地理编码,获取经纬度坐标,然后再进行空间数据可视化。本文采用百度地图API进行地理编码。

由于百度地图API获取的地理编码为百度经纬度坐标bd09ll,是在国测局坐标gcj02ll(火星坐标系)对实际坐标/谷歌地图坐标WGS84的非线性加密的基础上进行二次线性加密的结果,因此需要进行坐标转换,根据GIS底图的不同使用相应的结果。本文采用GitHub wandergis 提供的开源源码进行地理编码。

本人结合二者功能,面向对象,自主设计地理编码和坐标转换工具,进行地理编码与坐标转换工具。

4.2.1 代码分析

  1. 在案例中,程序运行的流程是在使用百度地图API进行地理编码后,再进行从bd09ll到WGS84坐标的转换。而坐标转换工具具有WGS84、gcj02ll、bd09ll三相转换功能,因此,程序将坐标转换工具作为父类首先进行设计。
import requests,urllib
import pandas,math
import os

class Coordinate_Transform(object):

    x_pi = 3.14159265358979324 * 3000.0 / 180.0
    pi = 3.1415926535897932384626  # π
    a = 6378245.0  # 长半轴
    ee = 0.00669342162296594323  # 偏心率平方

    def __init__(self,file_path,lng_collumn,lat_collumn,from_type,to_type):
        self.file_path=file_path
        self.lng_collumn,self.lat_collumn=lng_collumn-1,lat_collumn-1
        self.from_type,self.to_type=from_type,to_type #wgs,gcj,bd

    def _create(self):
        if os.path.splitext(self.file_path)[-1] == '.csv':
            dataframe = pandas.read_csv(self.file_path, header=0, index_col=None)
        if os.path.splitext(self.file_path)[-1] == '.xlsx':
            dataframe = pandas.read_excel(self.file_path, header=0, index_col=None)
        if os.path.splitext(self.file_path)[-1] == '.xls':
            dataframe = pandas.read_excel(self.file_path, header=0, index_col=None)

        if self.to_type == 'wgs':
            df_to_columns=pandas.DataFrame(columns=['lng_wgs', 'lng_wgs'])
        if self.to_type == 'gcj':
            df_to_columns=pandas.DataFrame(columns=['lng_gcj', 'lat_gcj'])
        if self.to_type == 'bd':
            df_to_columns=pandas.DataFrame(columns=['lng_bd', 'lat_bd'])
        #df_log = pandas.DataFrame(columns=['response', 'answer'])
        dataframe = pandas.concat([dataframe, df_to_columns], axis=1)
        return dataframe

    def _transform(self,lng,lat): # 三相转换函数
        if self.from_type=='gcj' and self.to_type=='bd':
            return self.gcj02_to_bd09(lng, lat)
        elif self.from_type=='bd' and self.to_type=='gcj':
            return self.bd09_to_gcj02(lng, lat)
        elif self.from_type=='wgs' and self.to_type=='gcj':
            return self.wgs84_to_gcj02(lng, lat)
        elif self.from_type=='gcj' and self.to_type=='wgs':
            return self.gcj02_to_wgs84(lng, lat)
        elif self.from_type=='bd' and self.to_type=='wgs':
            return self.bd09_to_wgs84(lng, lat)
        elif self.from_type=='wgs' and self.to_type=='bd':
            return self.wgs84_to_bd09(lng, lat)

    def do_transform(self):
        dataframe=self._create()
        for i in range(len(dataframe)):
            lng,lat = dataframe.iloc[i, self.lng_collumn],dataframe.iloc[i,self.lat_collumn]
            dataframe.iloc[i,-2],dataframe.iloc[i,-1]=self._transform(lng,lat)
        dataframe.iloc[:,:-2].to_excel(os.path.splitext(self.file_path)[0]+'_result.xlsx')
        print('Success')

	# 以下为GitHub wandergis 设计的坐标转换核心代码,输出为两个浮点数(float),详见源代码
    def out_of_china(self,lng, lat):
    def _transformlat(self,lng, lat):
    def _transformlng(self,lng, lat):
    def bd09_to_gcj02(self, bd_lng, bd_lat):
    def gcj02_to_wgs84(self,gcj_lng, gcj_lat):
    def bd09_to_wgs84(self,bd_lng, bd_lat): 
    def wgs84_to_gcj02(self,wgs_lng, wgs_lat):
    def gcj02_to_bd09(self,lng, lat):
    def wgs84_to_bd09(self,wgs_lng, wgs_lat):

代码应用方法:

from Coordinate_Transform import Coordinate_Transform

test_task=BaiduMapAPI_Geocoder(file_path,lng_collumn,lat_collumn,from_type,to_type)
# 例如:test_task=BaiduMapAPI_Geocoder('C:/Users/TEST/Desktop/静安教育分析/静安区学校列表.xlsx',14,15,'bd','wgs')
# file_path:可以使用.xls、.xlsx、.csv等三种文件格式
# lng_collumn,lat_collumn:为经度列、纬度列位置序号
# from_type,to_type:'bd'、'gcj'、'wgs'

test_task.do_transform()
  1. 由此,基于坐标转换父类进行设计百度地图地理编码及转换工具。
    注意: 需要准备好在百度地图开放平台(http://lbsyun.baidu.com/) 申请的AK
import requests
import urllib
import os
import pandas
from Coordinate_Transform import Coordinate_Transform

class BaiduMapAPI_Geocoder(Coordinate_Transform):
    ak=''# 此处填入您在 百度地图开放平台(http://lbsyun.baidu.com/)申请的AK

    def __init__(self,file_path,address_collumn,city):
        self.file_path=file_path
        self.address_collumn=address_collumn
        self.city=city

    def _create(self):
        if os.path.splitext(self.file_path)[-1]=='.csv':
            dataframe = pandas.read_csv(self.file_path, header=0, index_col=None)
        if os.path.splitext(self.file_path)[-1]=='.xlsx':
            dataframe = pandas.read_excel(self.file_path, header=0, index_col=None)
        if os.path.splitext(self.file_path)[-1]=='.xls':
            dataframe = pandas.read_excel(self.file_path, header=0, index_col=None)
        df_bd = pandas.DataFrame(columns=['lng_bd', 'lat_bd'])
        df_gcj=pandas.DataFrame(columns=['lng_gcj', 'lat_gcj'])
        df_wgs=pandas.DataFrame(columns=['lng_wgs', 'lng_wgs'])
        df_log = pandas.DataFrame(columns=['confidence','comprehension','response', 'answer'])
        dataframe = pandas.concat([dataframe,df_bd,df_gcj,df_wgs, df_log], axis=1,ignore_index=True)
        return dataframe

    def _api_bd09ll(self,address):
        url_base='http://api.map.baidu.com/geocoding/v3/?'
        params= {'address':address,
                 'city': self.city,
                 'ret_coordtype':'bd09ll',
                 'ak': self.ak,
                 'output': 'json'}
        url=url_base+urllib.parse.urlencode(params)
        response = requests.get(url)
        answer = response.json()
        bd_lng,bd_lat=float(answer['result']['location']['lng']),float(answer['result']['location']['lat'])
        return response,answer,bd_lng,bd_lat

    def do_BaiduMapAPI_Geocoder(self):
        dataframe=self._create()
        for i in range(len(dataframe)):
            response,answer,bd_lng,bd_lat = self._api_bd09ll(dataframe.iloc[i, self.address_collumn-1])
            dataframe.iloc[i,-10],dataframe.iloc[i,-9]=bd_lng,bd_lat
            dataframe.iloc[i,-8],dataframe.iloc[i,-7]=Coordinate_Transform.bd09_to_gcj02(self,dataframe.iloc[i,-10],dataframe.iloc[i,-9])
            dataframe.iloc[i,-6],dataframe.iloc[i,-5]=Coordinate_Transform.bd09_to_wgs84(self,dataframe.iloc[i,-10],dataframe.iloc[i,-9])
            dataframe.iloc[i,-4],dataframe.iloc[i,-3],dataframe.iloc[i,-2],dataframe.iloc[i,-1]=answer['result']['confidence'],answer['result']['comprehension'],str(response),str(answer)
        dataframe.iloc[:,:-2].to_excel(os.path.basename(self.file_path)+'_result.xlsx')
        dataframe.to_excel(os.path.basename(self.file_path)+'_logfile.xlsx')
        print('Success')

代码应用方法:

from BaiduMapAPI_Geocoder import BaiduMapAPI_Geocoder
test_task=BaiduMapAPI_Geocoder(file_path,address_collumn,city)
# 例如:test_task=BaiduMapAPI_Geocoder('C:/Users/TEST/Desktop/静安教育分析/静安区学校列表.xlsx',3,'上海')
# file_path:可以使用.xls、.xlsx、.csv等三种文件格式
# address_collumn:为地址列位置序号
# city:地址所在的城市名。用于指定上述地址所在的城市,当多个城市都有上述地址时,该参数起到过滤作用,但不限制坐标召回城市。

test_task.do_BaiduMapAPI_Geocoder()

4.2.2 结果导出

通过运行代码,可以导出如下Excel表格,获取地理编码的百度坐标、经转换后的国测局和WGS84坐标,以及日志信息。
在这里插入图片描述

4.3 空间可视化分析

  1. 在ArcGIS中新建地图并定义工作环境

在这里插入图片描述
2. 导入Excel中的数据
在这里插入图片描述
在这里插入图片描述
3. 可以看到,在三种不同的坐标体系下,点的位置存在着不同程度偏移,这也为后续的应用打下基础。
在这里插入图片描述
4. 加载 天地图·上海 地图服务底图,进行点数据可视化。
在这里插入图片描述
5. 经观察,WGS84图层数据的偏移程度最低,因此利用该数据进行进一步分析。

(1) 核密度分析(密度)
在这里插入图片描述
(2) 欧氏距离(影响范围)

(3) 各级各类学校数据分类可视化
在这里插入图片描述

4 分析结果·需求达成

对静安教育资源数据及可视化结果进行初步分析,可知静安区教育资源丰富,各级各类学校计210所,详细信息如下表所示:
在这里插入图片描述
在空间分布上,以吴淞江(苏州河)和中环线-铁路南何支线为界分为三部分:
原静安区吴淞江(苏州河)以南地区,教育资源分布密集,学校面积普遍较小,与静安区狭小的面积与密集的人口相关;
原闸北区吴淞江(苏州河)以北地区至中环线地区,教育资源分布较为密集,其分布与人口居住分布密切相关,呈南密疏;
中环线-铁路南何支线附近布局较多工业与交通用地,居住人口较少的同时环境亦较差,教育资源呈空白;
原闸北区铁路南何支线以北地区,位于两区交界,面积较小而人口较少,教育资源密度较低。

在这里插入图片描述

4.1 进一步研究

在此研究的基础上,可以利用学校面积数据等进行进一步的教育土地资源分析,利用道路数据进行进一步的成本距离分析、网络分析等。

附 源码下载

地理编码和坐标转换工具 coordinate_transform_tools.zip

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HerbertHu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值