天天看點

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()