聚类算法 | 景区经纬度数据的抓取和聚类
Posted 数太极
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聚类算法 | 景区经纬度数据的抓取和聚类相关的知识,希望对你有一定的参考价值。
数据抓取
在抓取百度地图经纬度的时候,需要进行有参数的get请求,具体的参数值如下:
parameter = {
"newmap": "1",
"reqflag": "pcmap",
"biz": "1",
"from": "webmap",
"da_par": "direct",
"pcevaname": "pc4.1",
"qt": "con",
"c": City_Code, # 城市代码
"wd": key_word, # 搜索关键词
"wd2": "",
"pn": page, # 页数
"nn": page * 10,
"db": "0",
"sug": "0",
"addr": "0",
"da_src": "pcmappg.poi.page",
"on_gel": "1",
"src": "7",
"gr": "3",
"l": "12",
"tn": "B_NORMAL_MAP",
# "u_loc": "12621219.536556,2630747.285024",
"ie": "utf-8",
# "b": "(11845157.18,3047692.2;11922085.18,3073932.2)", #这个应该是地理位置坐标,可以忽略
"t": "1468896652886"
}
其中,注释的城市代码、搜索关键词和页数需要我们传值,其他的参数可以设置成默认,不用管。
城市代码可以到百度地图开发平台下载,下载的城市代码其实并不全,因为城市中有区、县,各个区县的城市代码也各不相同。不过,百度地图提供的城市代码,从其数量上和其覆盖面积来说,都足以满足需要。
搜索关键词,我传入的是景区,即key_word = '景区'。
页数从0开始是第一页,然后逐渐'page += 1',nn其实是当前城市代码下,请求到的数据的个数,这里传入的是page * 10,即每页请求10条数据。为了节约时间,在每个城市代码下,我仅请求了10条数据,就是说,没有做'page += 1'的操作,将近400个城市代码,每个城市代码请求10条数据,将近4000条数据,哪怕请求中有些城市代码获取不到10条数据,或者因为某种原因抛弃一些数据,也能保证数据量在3000以上。
K-Means聚类
K-Means聚类算法是很常用的一个聚类算法,是基于向量距离来做聚类。算法步骤如下:
(1)从n个向量对象中,任意取出k个向量作为初始聚类中心。
(2)计算每个向量对象与这k个中心向量的距离。
(3)把每个向量对象和距离它最近的中心向量归到一个类簇中。
(4)重新计算每个类簇的中心向量位置。
(5)重复步骤(3)(4),直到中心向量位置变动很小为止。
需要实现指定类簇的数量,并给定初始的类中心。
用抓取的景区数据为例,使用K-Means算法进行聚类。
python代码如下:
#coding=utf-8
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
# 从文件中读取景区经纬度数据
X = []
f = open("scenery.txt", 'r')
for line in f:
X.append([float(line.split(',')[2]), float(line.split(',')[3])])
# 转换成numpy array
X = np.array(X)
# 设置类簇的数量
n_clusters = 5
# 把数据和对应的分类数放入到聚类函数中进行聚类
cls = KMeans(n_clusters).fit(X)
# X中每个所属分类的y一个列表
# cls.labels_
# 画图
makers = ['^', 'x', 'o', '*', '+']
colors = ['r', 'g', 'b', 'yellow', 'm']
for i in range(n_clusters):
members = cls.labels_ == i
plt.scatter(X[members, 0], X[members, 1], s=60, c=colors[i], marker=makers[i], alpha=0.5)
plt.title('KMeans')
plt.show()
绘制的图形效果如下:
根据绘制的图形可以看到,整体偏向右上角,只有一个紫色的加号作为一类在左下角,并且其经纬度为(0,0),可以认定,这个点是在处理中产生的异常点,需要将其去除。
for line in f:
lat = float(line.split(',')[2])
lng = float(line.split(',')[3])
if lat > 0 and lng > 0:
X.append([lat, lng])
处理后的聚类效果如下:
这个图跟标准的地图有所偏差,如果以上北下南,左西右东来看,东北和西南是没有问题的,但是西北和东南恰好相反,如果沿着左下到右上的对角线,翻转一下,刚好跟正常的地图相符。
层次聚类
层次聚类和人类“自底向上”认识事物的过程是一样的。层次聚类是通过聚类算法把样本根据距离分成若干个大群,大群之间相异,大群内部相似,而大群内部又可以当作一个全局样本,再继续划分若干个小群,小群之间相异,小群内部相似,如此分下去,最后形成的是一棵数的结构。
层次聚类的Python代码和K-Means聚类相似,只是聚类方法不同而已。代码如下:
#coding='utf-8'
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering
# 从文件中读取景区经纬度数据
X = []
f = open("scenery.txt", 'r')
for line in f:
lat = float(line.split(',')[2])
lng = float(line.split(',')[3])
if lat > 0 and lng > 0:
X.append([lat, lng])
# 转换成numpy array
X = np.array(X)
# 设置类簇的数量
n_clusters = 5
# 使用方差最小化的方法ward
cls = AgglomerativeClustering(linkage='ward', n_clusters=n_clusters).fit(X)
# X中每个所属分类的y一个列表
# cls.labels_
# 画图
makers = ['^', 'x', 'o', '*', '+']
colors = ['r', 'g', 'b', 'yellow', 'm']
for i in range(n_clusters):
members = cls.labels_ == i
plt.scatter(X[members, 0], X[members, 1], s=60, c=colors[i], marker=makers[i], alpha=0.5)
plt.title('Agglomerative')
plt.show()
层次聚类效果如下:
其实,我并没有看出来这个效果与K-Means聚类有什么区别。简直是一模一样。
城市代码数据:链接:https://pan.baidu.com/s/1PulJnpTNwRvRkbl73ONhYw 密码:boe6
景区经纬度数据:链接:https://pan.baidu.com/s/1JX-E20Pde0_971-J9n174w 密码:rris
以上是关于聚类算法 | 景区经纬度数据的抓取和聚类的主要内容,如果未能解决你的问题,请参考以下文章