【数据分析进阶】DCIC竞赛-task2 数据可视化
本节目标:完成出租车轨迹可视化与出租车热度可视化
数据可视化介绍
数据可视化(Data Visualization)是聚焦数据表现形式的领域,如何将信息进行抽象、对比和展示的方法。数据可视化在不断发展,可供使用的工具和展示形式在不断演变。与数据科学的其他方向相比(机器学习和数据挖掘),可视化涵盖的技术方法更多,形式更加多样。
下图,未来美国的人口统计数据(不同年龄阶段)
从0-100岁人口年龄的分布
下图,电影对白(按性别划分)
数据可视化按用途可以划分为
- 数据统计展示;
- 数据分布展示;
- 数据对比展示;
数据可视化在机器学习&深度学习中应用广泛,如特征相关性热力图、特征分布趋势图、梯度可视化图和特征重要性直方图。
在交通领域,数据可视化同样用途广泛:
- 通过可视化可以找到热门的区域,定位到拥堵区域;
- 通过可视化可以找到热门的线路,定位拥堵线路;
- 通过可视化可以找到交通的流量;
无一例外,现有地图大数据报告都使用可视化的方式进行呈现:
- 百度交通大数据报告:https://jiaotong.baidu.com/reports/
- 滴滴交通大数据报告:https://sts.didiglobal.com/
- 高德交通大数据报告:https://report.amap.com/diagnosis/index.do
- 腾讯地图大数据:https://heat.qq.com/
常规可视化
基本流程
- 学习可视化的组成元素;
- 学习可视化的常见图像案例;
- 学习可视化库的使用;
可视化组成元素
圆圈表示各部分名称,通过官网例子可以获知每一部分是怎么用的https://matplotlib.org/3.3.1/gallery/showcase/anatomy.html
如上图在绘制一张图的过程中,有较多的细节需要注意,上图来源为matplotlib。一张图包含的具体的组成元素如下:
- 坐标轴、坐标轴标题;
- 图表标题、数据标签;
- 误差线、网格线;
- 图例等;
可视化图标类型
- 饼图(Pie Chart)或称饼状图,是一个划分为几个扇形的圆形统计图表。在饼图中,每个扇形的弧长(以及圆心角和面积)大小,表示该种类占总体的比例,且这些扇形合在一起刚好是一个完全的圆形。能够显示的取值的比例
- 散点图(Scatter Plot)是在笛卡尔座标上放置一系列的数据点,用来显示两个变量的数值(每个轴上显示一个变量),并检测两个变量之间的关系或相关性是否存在。
通过散点图可以发现两个变量是线性相关还是非线性,是正相关还是负相关,是强相关还是弱相关
-
条形图(Bar Chart)采用水平或垂直条形(柱形图)来比较不同类别的离散数值。图表其中一条轴代表要比较的具体类别,另一条则用作离散数值的标尺。更侧重数据具体的大小关系
-
箱形图(又称为「盒须图」或「箱线图」)能方便显示数字数据组的四分位数。
可以从箱形图得出的观察结果: -
关键数值,例如平均值、中位数和上下四分位数等
-
任何异常值(以及它们的数值)
-
数据分布是否对称
-
数据分组有多紧密
-
数据分布是否出现偏斜(如果是,往什么方向偏斜)
更多图形见
地图可视化
地图可视化方法如下:
- 点示地图 (Dot Map) 在地理区域上放置相等大小的圆点,旨在检测该地域上的空间布局或数据分布。
- 气泡地图指定地理区域上方会显示圆形图案,圆形面积与其在数据集中的数值会成正比。
- - 连接地图 (Connection Map) 即是用直线或曲线连接地图上不同地点的一种图表。
- 流向地图 (Flow Map) 在地图上显示信息或物体从一个位置到另一个位置的移动及其数量,通常用来显示人物、动物和产品的迁移数据。
- 地区分布图通常用来显示不同地理分区或区域(不同颜色或图案)与数据变量之间的关系,并把所显示位置的数值变化或模式进行可视化处理。
赛题可视化
以巡游车GPStaxiGps20190531.csv为案例进行数据统计
1. 24小时巡游成统计数量
含义 | |
---|---|
RUNNING_STATUS/OPERATING_STATUS | 运营状态(空车(1)、载客(2)、电召(4)、停运(8)、交班(16)、包车(32)) |
GPS_SPEED | GPS速 |
DRIVING_DIRECTION | 行驶方向角 |
GPS_TIME | 卫星定位时间 |
LONGITUDE | 经度(WGS84 GPS标准) |
LATITUDE | 纬度(WGS84 GPS标准) |
CARNO | 车牌号 |
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
INPUT_PATH = './input/' #文件目录
MAX_ROWS = None # 文件读取行数
taxigps2019 = pd.read_csv(INPUT_PATH + 'taxiGps20190531.csv', nrows=MAX_ROWS,
dtype = {
'DRIVING_DIRECTION': np.uint16,
'OPERATING_STATUS': np.uint8,
'LONGITUDE': np.float32,
'LATITUDE': np.float32,
'GPS_SPEED': np.float16
})
taxigps2019=taxigps2019[taxigps2019.columns[::-1]]
#原始数据不是按照汽车编号还有GPS时间进行排序的
#按照相同车,相同时间进行排序
taxigps2019.sort_values(by=['CARNO','GPS_TIME'], inplace=True)
taxigps2019.reset_index(inplace=True, drop=True)
#将时间转换为datatime格式
taxigps2019['GPS_TIME']=pd.to_datetime(taxigps2019['GPS_TIME'])
taxigps2019['GPS_TIME_hour']=taxigps2019['GPS_TIME'].dt.hour
#统计每个小时汽车['CRANO']的nunique
#x轴画的是被分组的的列
taxigps2019.groupby(['GPS_TIME_hour'])['CARNO'].nunique().plot()
plt.ylabel('Car Count')
2. 24小时巡游车平均GPS速度
#为了处理异常数据,此处使用np.cilp对异常数据进行映射
#凡是大于150的都处理为150小于0的数据都映射为0
taxigps2019['GPS_SPEED_clear'] = np.clip(taxigps2019['GPS_SPEED'].values,0,150)
taxigps2019['GPS_SPEED_clear'].value_counts()
#taxigps2019['GPS_SPEED'].value_counts()
#设置图像大小
fig=plt.figure(figsize=(10,8))
taxigps2019.groupby(['GPS_TIME_hour'])['GPS_SPEED'].mean().plot()
# 剔除掉为0的数据后画出GPS平均速度和时间的关系
taxigps2019[taxigps2019['GPS_SPEED_clear'] != 0].groupby(['GPS_TIME_hour'])['GPS_SPEED_clear'].mean().plot()
#蓝线统计所有速度的 黄线统计的剔除掉0的
#剔除掉为0的时候10-16时候平均速度相较于不剔除的差异很多
#在这个时间段可能走走停停
#而在晚上非0的相对较少(renshao)
plt.legend(['Mean GPS Speed, contain 0', 'Mean GPS Speed, not contain 0'])
3. 24小时巡游车平均运营车辆
状态一空车,状态8停运
import matplotlib.pyplot as pyplotlt
import matplotlib.font_manager as fm
#0为空车
df=taxigps2019[taxigps2019['OPERATING_STATUS']==1]
df.groupby(['GPS_TIME_hour'])['CARNO'].nunique().plot()
#8为停运
df=taxigps2019[taxigps2019['OPERATING_STATUS']==8]
df.groupby(['GPS_TIME_hour'])['CARNO'].nunique().plot()
#图例
plt.legend(['STATUS 1','STATUS 8'])
4.某时间出租车位置分布
#地图可视化组件
import folium
from folium import plugins
from folium.plugins import HeatMap
#ocation的格式为[纬度,经度],zoom_start表示初始地图的缩放尺寸,数值越大放大程度越大
map_hooray = folium.Map(location=[24.482426, 118.157606], zoom_start=14)
#iloc比较简单,它是基于索引位来选取数据集,0:4就是选取 0,1,2,3这四行,需要注意的是这里是前闭后开集合
HeatMap(taxigps2019[['LATITUDE', 'LONGITUDE']].iloc[:1000].values).add_to(map_hooray)
#因为图片资源在国外过亿需要等一会才能显示出来
map_hooray
5. 某个巡游车具体的路线
import folium
# Create the map and add the line
m = folium.Map(location=[24.482426, 118.157606], zoom_start=12)
my_PolyLine=folium.PolyLine(locations=taxigps2019[taxigps2019['CARNO'] == '0006d282be70d06881a7513b69fcaa60'][['LATITUDE', 'LONGITUDE']].iloc[:50].values,weight=5)
m.add_children(my_PolyLine)
学习资源
思考
如何统计得到所有巡游车中运营时间最长的车?
统计每辆车运营的分钟数在进行max或者sort_values排序
#sort_values用法
taxiorder2019.sort_values(by=['CARNO','GETON_DATE'], inplace=True)
如何根据巡游车路线得到具体的运营规律?
练习题
做的时候主要问题在数据的读取,如何能够实现数据的批量读取避免重复劳动,以及数据的内存问题,自己的代码虽然编出来了,但是用的复制粘贴大法太辣眼了,此处只放阿水大佬的参考答案
其中使用glob实现批量读取,gc回收机制避免内存爆炸,split提取需要部分都是值得学习的
可视化巡游车20190531 - 20190609 期间早上9点的平均速度变化;
#导入包
import pandas as pd
import numpy as np
import glob,gc
#glob用于文件读取,gc实现垃圾回收,参考https://www.cnblogs.com/hshp/p/10466662.html
#设置文件读取路径
paths=glob.glob('./input/taxiGps/taxiGps20190*.csv')
paths.sort()
paths
#计算各天就点的平均速度并将其存入speed中
#计算九点的速度的时候也可以直接用df['GPS_TIME_hour']==9来实现
speed=[]
for path in paths:
#读取数据
df=pd.read_csv(path)
df['GPS_TIME']=pd.to_datetime(df['GPS_TIME'])
df['GPS_TIME_hour']=df['GPS_TIME'].dt.hour
print(path,df.groupby(['GPS_TIME_hour'])['GPS_SPEED'].mean().loc[9])
speed.append(df.groupby(['GPS_TIME_hour'])['GPS_SPEED'].mean().loc[9])
#释放内存
del df;
gc.collect()
import matplotlib.pyplot as plt
%matplotlib inline
#可视化部分
plt.plot(range(len(paths)),speed)
#设置x轴刻度
#原格式为./input/taxiGps\taxiGps20190609.csv
#[-1=取划分后的最后一个即taxiGps20190609.csv
#[7:-4]从axiGps20190609.csv中提取出了20190609
#rotation=30 设置x轴标签倾斜角度
_ = plt.xticks(range(len(paths)), [x.split('/')[-1][7:-4] for x in paths], rotation=30)
plt.ylabel('Speed')
plt.savefig('speed.jpg',dpi=200,bbox_inches='tight')
可视化统计巡游车20190531 - 20190609 期间平均每辆巡游车运营时间(一天之内活跃的分钟个数)变化;
#导入相关的包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import glob,gc
#设置路径
paths=glob.glob('./input/taxiGps/taxiGps20190*.csv')
paths.sort()
#统计时间并将其放到数组中
minute=[]
for path in paths:
#只使用这两列属性
df=pd.read_csv(path,usecols=['CARNO','GPS_TIME'])
#原始的时间数据为2019/5/31 0:00:05,通过下面的操作保留到了分钟
df['GPS_TIME']=df['GPS_TIME'].apply(lambda x: x[:-3])
minute.append(df.groupby(['CARNO'])['GPS_TIME'].nunique().mean())
#输出数组中的最后一个,也就是新加入的
print(path,minute[-1])
del df;
gc.collect()
#进行可视化
plt.plot(range(len(paths)),minute)
#设置x轴标签
_ = plt.xticks(range(len(paths)), [x.split('/')[-1][7:-4] for x in paths], rotation=30)
plt.ylabel('Minute')
plt.savefig('minute.jpg',dpi=200,bbox_inches='tight')