天天看点

python地理位置聚类_基于地理位置标记的空间聚类分析(python-DBSCAN)

数据来源:通过www.flickr.com/services/api接口抓取带地理标记的flickr图片及属性数据,筛选年份,经过数据清洗,得到样本数据。

使用软件:python 3

需求:得到热点区域AOI

参考文献:

1.《基于地理标记照片的北京市入境旅游流空间特征》

2.https://www.cnblogs.com/pinard/p/6208966.html

具体思路:

首先将数据进行整理、清洗;然后使用Python scikit-learn中的DBSCAN聚类方法,选择合适的搜索半径,以及个数点,得到聚类结果;求出没个聚类点的中心位置,就可得到热点区域AOI。

聚类DBSCAN算法:

DBSCAN是基于一组邻域来描述样本集的紧密程度的,参数(ϵϵ, MinPts)用来描述邻域的样本分布紧密程度。其中,ϵϵ描述了某一样本的邻域距离阈值,MinPts描述了某一样本的距离为ϵϵ的邻域中样本个数的阈值。

假设我的样本集是D=(x1,x2,...,xm)(x1,x2,...,xm),则DBSCAN具体的密度描述定义如下:

1) ϵϵ-邻域:对于xj∈Dxj∈D,其ϵϵ-邻域包含样本集D中与xjxj的距离不大于ϵϵ的子样本集,即Nϵ(xj)={xi∈D|distance(xi,xj)≤ϵ}Nϵ(xj)={xi∈D|distance(xi,xj)≤ϵ}, 这个子样本集的个数记为|Nϵ(xj)||Nϵ(xj)|

2) 核心对象:对于任一样本xj∈Dxj∈D,如果其ϵϵ-邻域对应的Nϵ(xj)Nϵ(xj)至少包含MinPts个样本,即如果|Nϵ(xj)|≥MinPts|Nϵ(xj)|≥MinPts,则xjxj是核心对象。

3)密度直达:如果xixi位于xjxj的ϵϵ-邻域中,且xjxj是核心对象,则称xixi由xjxj密度直达。注意反之不一定成立,即此时不能说xjxj由xixi密度直达, 除非且xixi也是核心对象。

4)密度可达:对于xixi和xjxj,如果存在样本样本序列p1,p2,...,pTp1,p2,...,pT,满足p1=xi,pT=xjp1=xi,pT=xj, 且pt+1pt+1由ptpt密度直达,则称xjxj由xixi密度可达。也就是说,密度可达满足传递性。此时序列中的传递样本p1,p2,...,pT−1p1,p2,...,pT−1均为核心对象,因为只有核心对象才能使其他样本密度直达。注意密度可达也不满足对称性,这个可以由密度直达的不对称性得出。

5)密度相连:对于xixi和xjxj,如果存在核心对象样本xkxk,使xixi和xjxj均由xkxk密度可达,则称xixi和xjxj密度相连。注意密度相连关系是满足对称性的。

效果图:

python地理位置聚类_基于地理位置标记的空间聚类分析(python-DBSCAN)

Python代码:

import numpy as np,pandas as pd

from sklearn.cluster import DBSCAN

from shapely.geometry import MultiPoint

import geopandas

import shapefile

from matplotlib import pyplot as plt

plt.title("北京市游客地理标记城区空间聚类结果")

plt.scatter(latlngs[:,0],latlngs[:,1], s=1, c="black", marker='.')

border_shape=shapefile.Reader(shape_path)

border_shape_2=shapefile.Reader(shape_path_2huan)

border_shape_5=shapefile.Reader(shape_path_5huan)

border=border_shape.shapes()

border_2=border_shape_2.shapes()

border_5=border_shape_5.shapes()

#聚类中心区域

def get_centermost_point(cluster):

centroid = (MultiPoint(cluster).centroid.x, MultiPoint(cluster).centroid.y)

print(centroid)

return tuple(centroid)

# #渲染聚类结果

for border_detail in clusters:

x ,y= [],[]

for cell in border_detail:

x.append(cell[0])

y.append(cell[1])

plt.scatter(x, y,marker='o')

plt.show()