具体工作内容:
需要定位上海,北京,广东省,天津,湖北省,重庆,福建省内外边界的企业,得到这些企业距离边界的垂直距离。企业范围为上述7个省市+7个省市相邻的省市的企业。
已有数据:
上市公司excel文件(坐标格式为wgs1984)
办公地址的shp文件
注册地址的shp文件
输出格式:csv
字段:股票代码,股票名称,公司地址,是否是办公地址(1为是,0为否)、省份、距离哪一个省市的边界(例如,湖北省),距离边界的距离(单位:米)
一、arcgis数据预处理
预处理也可以用Python写,这里为了可视化了解数据就在Arcgis Pro中完成。
- 将省市边界和公司 统一投影到 WGS_1984_UTM_Zone_46N 以计算距离
- 定位七个省市 内外边界的企业
- 提取给定范围内的公司
- 股票代码去重
有些公司股票代码重复出现,如果地址是一样的,可当做同一家公司,在输出文件中占一行即可。
二、geopandas函数
距离实例
from shapely.geometry import Point
from shapely.geometry import LineString
point = Point([1,1])
line = LineString(((0,0), (1,1), (1,0)))
dist = point.distance(line)
h_dist = point.hausdorff_distance(line)
print(dist)
print(h_dist)
GeoDataFrame对象的空间拓扑分析方法包括contains()、within()、crosses()、intersects()等,参数是指定的几何对象,返回类型为布尔值的Series对象。
Bug:The indices of the two GeoSeries are different
解决方案:https://gis.stackexchange.com/questions/375407/geopandas-intersects-doesnt-find-any-intersection
例子可视化方案,耗时长,不适合批处理:https://medium.com/analytics-vidhya/calculating-distances-from-points-to-polygon-borders-in-python-a-paris-example-3b597e1ea291
三、完整代码
#读取shp
import geopandas as gpd
import pandas as pd
import numpy as np
boundry = gpd.read_file(r'七省及其边界_20\七省及其边界_20.shp',
encoding="utf8")
office_addr = gpd.read_file(r'办公地址_utm_七省内外边界\办公地址_utm_七省内外边界.shp',
encoding="utf8")
#使boundry 省份名和shp同步
boundry['省'] = boundry['省'].str[:2]
#可视化
ax1 = office_addr.plot(color="r",markersize=4)
boundry.plot(ax=ax1,color="gray",zorder=0)
#数据处理
result =pd.DataFrame(columns=('股票名称','股票代码','公司地址','省份','是否是办公地址','距离哪一个省市的边界','距离边界的距离'))
#将计算结果逐行插入result,注意变量要用[]括起来,同时ignore_index=True,否则会报错,ValueError: If using all scalar values, you must pass an index
#遍历公司,所在及相邻多边形 最短距离
for index,row in office_addr.iterrows(): # Looping over all points
#扩展检索省份
newdf = gpd.GeoDataFrame(np.repeat(boundry[boundry['省']==row['省份']].values, 20, axis=0), columns=boundry.columns)
newdf = newdf.set_crs(32646)
shares_boundary = boundry[boundry.geometry.intersects(newdf)] #肯定有所在省份和至少一个相邻省份
# Calculating dist for the neighbor polygon
for index2,row2 in shares_boundary.iterrows():
# for target in shares_boundary:
dist = gpd.GeoSeries(row2.geometry).boundary.distance(gpd.GeoSeries(row.geometry)).values[0]
result=result.append(pd.DataFrame(
{'股票名称':[row['股票名']],'股票代码':[row['股票代']],'公司地址':[row['办公地']],'是否是办公地址':1,'省份':[row['省份']],'距离哪一个省市的边界':[row2['省']],'距离边界的距离':[dist]} #variable 要加[]
),ignore_index=True)
result.to_csv('办公地址result.csv')
注册地址同理
四、工作时间
3.1
21:00-22:00 数据准备 投影
3.2
11:30-2:30 遍历点,所在及相邻多边形 最短距离 思路整理
17:00-18:00 arcgis脚本开发
20:00-23:00 内置modelbuiler构建尝试失败,bug太多,不如代码灵活
3.3
9:00-11:00 编写geopandas代码+运行