智慧海洋task 01
本次数据挖掘组队学习的内容来自于2020DCIC智能算法赛-智慧海洋建设,该赛题旨在于通过分析渔船北斗设备位置数据,具体判断出是拖网作业、围网作业还是刺网作业,本质上是序列数据的分类问题。Task 01主要是学习Python中地理空间数据分析工具shapely、folium、kepler.gl、geohash等的使用。*
1. shapely的介绍及使用
shapely是Python中的几何对象库,支持对于点(Point)、线(Curve)、面(Surface)等几何对象的操纵(主要是通过shapely.geometry进行处理)。
shapely主要是通过shapely.geometry(简记为geo)中Point类里的方法对点对象进行操纵
# point有三种赋值方式,具体如下
point = geo.Point(0.5,0.5)
point_2 = geo.Point((0,0))
point_3 = geo.Point(point)
# 其坐标可以通过coords或x,y,z得到
print(list(point_3.coords))
print(point_3.x)
print(point_3.y)
print(np.array(point))#可以和np.array进行互相转换
# 批量进行可视化
geo.GeometryCollection([point,point_2])
在shapely中可以通过LineString.LinearRing来对线对象进行操纵,二者不同之处在于通过LineString得到的线对象必须通过指定点来得到封闭线挑,而geo.LinearRing则默认指定第1个点和最后一个点相连(要求点的数目在3个以上)
- LineString中常用的类方法有:distance、hausdorff_distance、area、bounds、geom_type、coords、envelope(求最小外接矩形)、minimum_rotated_rectangle(求最小外接旋转矩形)、interpolate(插值:其中normalized=True时distance需要输入对应的分位数)、project(normalized=True时计算对应的点)
- DouglasPucker算法:(1) 将曲线的第一个点(作为anchor)和最后一个点(作为floater)连成一条直线,计算所有中间点到该直线的最大距离Dmax。(2)如果Dmax<D(预先设置的阈值),则该段只保留第一个和最后一个点,该段处理结束;(3)反之,用Dmax对应的中间点将曲线分为两段,对这两段重复第一步和第二步。直到递归结束后,将保留的点依次连接,组成简化后的曲线. LineString中执行该算法的方法为simplify
- LineRings:在geo中还有一个操纵线对象的类LinearRings,该类是geo.polygon的子类,用于创建3个点以上的封闭线对象
Shapely中主要通过Polygon类来对多边形对象进行创建和操纵:Polygon接受两个位置参数,第一个位置参数是和LinearRing一样,是一个有序的point元组。第二个位置参数是可选的序列,其用来指定内部的边界,如下例所示:
from shapely.geometry import Polygon
polygon1 = Polygon([(0, 0), (1, 1), (1, 0)])
ext = [(0, 0), (0, 2), (2, 2), (2, 0)]
int = [(1, 0), (0.5, 0.5), (1, 1), (1.5, 0.5)]
polygon2 = Polygon(ext, [int])
- Shapely中对多边形的操作的主要方法有:area、length(计算该多边形内外边界的长度)、exterior(外围坐标点)等
*shapely中还可以对几何对象的关系的操纵运算:contains(判断二者是否有包含关系)、crosses(判断两个对象内部是否相交)、disjoint(判断两个对象是否完全不相交)、intersects(判断两个对象是否相交)、convex_hull(计算包含所有点的凸多边形)
2. geopandas
geopandas是一个地理空间数据处理的工具,该方法扩展了pandas的数据类型,允许对几何对象进行空间操纵,其中几何对象的运算通过shapely来进行。Geopandas进一步依赖fiona进行文件访问,依赖matplotlib进行绘图。
geopandas中包含两种数据类型:GeoSeries和GeoDataFrame,实际上就是pandas在地理空间数据处理中的扩展。这两个数据结构可以当做地理空间数据的存储器,shapefile文件的pandas呈现。如下代码就是通过geopandas中的内置数据集来绘制世界地图
import pandas as pd
import geopandas
import matplotlib.pyplot as plt
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))#read_file方法可以读取shape文件,转化为GeoSeries和GeoDataFrame数据类型。
world.plot()#将GeoDataFrame变成图形展示出来,得到世界地图
plt.show()
3. Folium、Kepler.gl
Folium和Kepler.gl是进行地理数据可视化的工具,folium可以满足我们平时常用的热力图、填充地图、路径图、散点标记等高频可视化场景,而Kepler.gl则主要针对CSV、JSON以及GeoJSON类型的数据进行可视化处理
- 如针对北京地区的数据可以采用Folium进行热力图可视化:
import folium
import numpy as np
from folium.plugins import HeatMap
#先手动生成data数据,该数据格式由[纬度,经度,数值]构成
data=(np.array([[39.9,116.4,1]])+np.random.normal(size=(50,3))*np.array([[1,1,1]])).tolist()
m=folium.Map(location=[39.9,116.4],zoom_start=6)
HeatMap(data).add_to(m)
m
- 而对于本次赛题的数据则采用Kepler.gl进行可视化处理(可视化之前首先要对得到渔船的经纬度数据,进行数据清洗之后得到干净数据df_gpd_change.csv):
map1=KeplerGl(height=800)#zoom_start与这个height类似,表示地图的缩放程度
map1.add_data(data=df_gpd_change,name='data')
map1
最终得到渔船的轨迹图如下(因为数据原因,导致显示在陆地上捕鱼…)
4. GeoHash
在实际地理数据的处理中,若直接采用经纬度来进行计算,考虑到样本数目有时非常大,这必然会导致样本之间相关信息(如距离)计算时计算量的巨幅增加,为了计算的高效性,一般采用GeoHash编码对经纬度信息进行处理:该编码将地理经纬度坐标通过二分法将其转换为二进制编码,并将经纬二进制编码通过位置运算得到综合二进制编码,进一步将二进制转化为十进制,最后映射为字符和数字的组合。具体操作原理在地理空间索引:GeoHash原理一文中。GeoHash编码有如下几个特性:
- (1) 层级空间数据结构,将地理位置用矩形网格划分,同一网格内地理编码相同
- (2) 可以表示任意精度的地理位置坐标,只要编码长度足够长
- (3) 编码前缀匹配的越长,地理位置越邻近
由于编码本身是对信息的压缩,因此GeoHash算法不可避免的存在一些问题: - (1) 由于GeoHash使用Z形曲线来顺序填充空间的,而Z形曲线在拐角处会有突变,这表现在有些相邻的网格的编码前缀比其他网格相差较多,因此利用前缀匹配可以找到一部分邻近的区域,但同时也会漏掉一些
- (2) 一个网格内部所有点会共用一个GeoHash值,在网格的边缘点会匹配到可能较远但是GeoHash值相同的点,而本来距离较近的点却没有匹配到。这种问题可以这样解决:适当增加GeoHash编码长度,并使用周围的8个近邻编码来参与,因为往往只使用一个GeoHash编码可能会有严重风险!
参考文献:
[1] https://tianchi.aliyun.com/forum/postDetail?postId=110644
[2]https://blog.csdn.net/zhufenghao/article/details/85568340
[3]https://github.com/datawhalechina/team-learning-data-mining/tree/master/wisdomOcean