通过kmeans分析出租车数据并进行可视化
(1)数据准备
采用数据为出租车载客时的GPS记录数据集,数据格式为CSV,CSV格式是数据分析中常见的一种数据格式。CSV(Comma-Separated Values) 即逗号分隔值,文件以文本的方式存储表格数据(包含数字和文本)。其中每一行代表一条记录,每条记录被逗号分隔为字段,并且每条记录都有同样的字段序列。本实验一共181230条记录,具体文件格式见下表:
数据集地址:https://pan.baidu.com/s/150Pkps0VTq2-Q66RYvGxjQ?pwd=1111
提取码:1111
tid | lat | lon | time |
---|---|---|---|
1 | 30.624815 | 104.136585 | 212118 |
1 | 30.626615 | 104.133359 | 180636 |
4 | 30.633123 | 104.076302 | 141935 |
(2)创建dataframe
采用Kmeans聚类方法,其对应的参数类型为DataFrame,因此在使用之前需要使用本地生成的Spark DataFrame类型,其创建Spark DataFrame的主要过程如下:
(1)引入与sql相关的包初始化Spark上下文。
from pyspark.sql import SparkSession
from pyspark import SparkContext
(2) 使用textFile函数读取csv文件创建taxi_data,然后使用map算子操作将按照逗号隔开的文本创建RDD。
taxi_data = sc.textFile(r"G:\pythonProject\pc\spark\data\taxi.csv")
taxi_rdd=taxi_data.map(lambda line:line.split(','))
(3)创建矢量RDD,矢量两个参数分别为纬度和经度。在下文的聚类函数中需要该格式RDD进行聚类。
from pyspark.ml.linalg import Vectors
taxi_row=taxi_rdd.map(lambda x: (Vectors.dense (x[1],x[2]), ))
(4)使用SparkSession创建sql上下文并使用createDataFrame创建DataFrame。
sqlsc=SparkSession.builder.getOrCreate()
taxi_df=sqlsc.createDataFrame(taxi_row,["features"])
(3)kmeans聚类分析
KMeans是最常用的聚类算法之一,它将数据点聚类成预定义的簇数。
KMeans 是一个迭代求解的聚类算法,其属于划分(Partitioning) 型的聚类方法,即首先创建K个划分,然后迭代地将样本从一个划分转移到另一个划分来改善最终聚类的质量。
它是一种无监督分类算法
KMeans方法中包含若干参数,其中k为分簇个数,seed为种子点
from pyspark.ml.clustering import KMeans
kmeans=KMeans(k=3, seed=1) #聚成3类
model=kmeans.fit(taxi_df) #注意,传入的DataFrame是矢量名称为features的集合
centers=model.clusterCenters() #产生聚类集合
print(centers)
# Kmeans方法中包含啊若干个参数,k为分簇个数,seed为种子点,上方为核心代码。
# 代码解析如下:
# 第一行:从pyspark.ml.clustering 中导入KMeans。
# 第二行:创建kmeans实例,k为分簇个数,seed为种子点。
# 第三行:调用kmeans.fit方法训练形成模型
# 第四行:产生聚类集合
# 第五行:输出集合
# 聚类的结果是一系列的点集,这些点集也就是出租车聚集的地区,上述代码将数据聚类成3类,如下
打印结果
由以上数据可知,出租车被分为三类,每一类的中心点经纬度为一个列表
(4)调用百度API进行数据可视化
使用百度地图接口需要百度的一个认证,也就是需要在登录百度地图开发平台申请key,开放平台地址:http://lbsyun.baidu.com/,申请key地址:http://lbsyun.baidu.com/apiconsole/key,申请界面如图所示:
申请过程:点击开放平台地址:http://lbsyun.baidu.com/
创建完成后复制你的ak
然后编写html页面
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html {width: 100%;height: 100%;margin:0;font-family:"微软雅黑";}
#allmap{width:100%;height:1000px;}
/*p{margin-left:5px; font-size:14px;}*/
</style>
<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=你的AK"></script>
<script src="//libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<title>给多个点添加信息窗口</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
// 百度地图API功能
map = new BMap.Map("allmap");
map.enableScrollWheelZoom(); //启用滚轮放大缩小,默认禁用
map.enableContinuousZoom();
map.centerAndZoom(new BMap.Point(104.08776376,30.64628505), 15);
var data_info = [[104.08776376,30.64628505,"经纬度:104.08776376,30.64628505"],
[103.65216803,30.89423206,"经纬度:103.65216803,30.89423206"],
[104.01714713,30.65637398,"经纬度:104.01714713,30.65637398"]
];
var opts = {
width : 250, // 信息窗口宽度
height: 80, // 信息窗口高度
title : "信息窗口" , // 信息窗口标题
enableMessage:true//设置允许信息窗发送短息
};
for(var i=0;i<data_info.length;i++){
var marker = new BMap.Marker(new BMap.Point(data_info[i][0],data_info[i][1])); // 创建标注
var content = data_info[i][2];
map.addOverlay(marker); // 将标注添加到地图中
addClickHandler(content,marker);
}
function addClickHandler(content,marker){
marker.addEventListener("click",function(e){
openInfo(content,e)}
);
}
function openInfo(content,e){
var p = e.target;
var point = new BMap.Point(p.getPosition().lng, p.getPosition().lat);
var infoWindow = new BMap.InfoWindow(content,opts); // 创建信息窗口对象
map.openInfoWindow(infoWindow,point); //开启信息窗口
}
</script>
运行查看结果