随着共享经济的兴起,共享单车已成为城市出行的重要方式之一。然而,共享单车的使用情况、分布情况以及用户行为等方面的信息仍然缺乏系统的分析和可视化。本项目旨在通过可视化技术,全面展示共享单车的使用情况,为城市规划和管理提供决策支持。
数据集中包括了美国共享单车公司Capital Bikeshare在华盛顿地区2011年和2012年的使用量历史记录,以及每天对应的天气信息。利用该数据集,可以对季节因素、天气因素等对单车使用量的影响进行分析。数据集中共包含16个特征,下表中展示了数据集所有特征的名称及对应含义:
字段名称 | 含义说明 |
---|---|
instant | 行数编码 |
dteday | 日期变量 |
season | 季节变量,编码1-4分别表示 1-3月、4-6月、6-9月,10-12月 |
yr | 年份变量,编码0代表2011年,1代表2012年 |
mnth | 月份编码,范围为1-12,代表1-12月 |
holiday | 是否为节假日,0代表不是,1代表是 |
weekday | 一周的第几天,范围为0-6 |
workingday | 是否为工作日,0代表不是,1代表是 |
weathersit | 天气类型,1代表晴朗少云,2代表多云雾, 3代表小雨/小雪/雷电 |
temp | 以摄氏度表示的标准化温度,值被除以41(最大值) |
atemp | 以摄氏度表示的标准化感觉温度,值被除以50(最大值) |
hum | 标准化湿度,值被除以100(最大值) |
windspeed | 标准化风速,值被除以67(最大值) |
casual | 未注册用户单车使用量 |
registered | 注册用户单车使用量 |
cnt | 所有用户单车使用量,包括未注册用户和注册用户 |
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from plotnine import *
%matplotlib inline
## 设置绘图时的中文字体
from matplotlib.font_manager import FontProperties
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False
首先,读取数据集:
## 读取数据
data_old = pd.read_csv('./Bike_Sharing_Dataset.csv')
## 查看数据的前5行
data_old.head()
## 查看数据集基本信息
data_old.info()
从结果中可以看出,数据集中共包含731条数据,均无缺失数据。
有些字段与数据分析无关,例如:字段instant
表示行数编码,可以直接删除。有些字段的含义较为接近,保留其一即可,例如:字段atemp
和temp
都表示温度,留下一个就可以。
data = data_old.drop(['instant', 'atemp', 'casual', 'registered'], axis=1)
为方便进行可视化后的观察,我们对各字段使用字典进行中文标识:
chs_name = {'dteday': '日期',
'season': '季节',
'yr': '年份',
'mnth': '月份',
'holiday': '节假日',
'weekday': '星期',
'workingday': '工作日',
'weathersit': '天气类型',
'temp': '温度',
'hum': '湿度',
'windspeed': '风速',
'cnt': '使用量'}
data.rename(columns=chs_name, inplace=True)
## 标识后的结果
data.head()
最后,我们查看各变量的字段类型,并统计个数、绘制条形图:
data_type_df = pd.DataFrame(data.dtypes.value_counts()).rename(columns={0: 'count'})
## 绘制条形图
data_type_df.plot(kind='bar',
title='字段类型个数条形图',
legend=False,
rot=360,
figsize=(8, 6))
在探究影响因素之前,我们首先通过直方图和箱线图来观察共享单车的使用量的分布情况。通过这两种图形,我们可以直观地了解使用量的频数分布和数据的中心趋势、离散程度以及异常值。
## 绘制直方图
plt.figure(figsize = (14,6))
plt.subplot(1, 2, 1)
plt.hist(data['使用量'],
bins=8,
facecolor='green',
alpha=0.5,
edgecolor='black')
plt.title('使用量直方图', fontsize=15)
plt.xlabel('使用量', fontsize=15)
plt.ylabel('频数', fontsize=15)
## 绘制箱线图
plt.subplot(1, 2, 2)
plt.boxplot(data['使用量'],
labels=['使用量'],
patch_artist = True,
boxprops = {'color':'black','facecolor':'yellow'},
flierprops = {'markerfacecolor':'red','color':'black'})
plt.title('使用量箱线图', fontsize=15)
plt.xticks(fontsize=12)
由结果图可知,单车使用量近似正态分布,且不存在异常值。
为了对比两年的共享单车使用量,我们将使用条形图和饼图进行可视化。这两种图形将帮助我们清晰地展示不同年份之间使用量的差异,并揭示哪一年或哪一个季节的使用量更高。
## 绘制条形图
### 分组聚合
count_grouped = data['使用量'].groupby(data['年份']).sum()
count_grouped_df = count_grouped.reset_index()
count_grouped_df['年份'] = count_grouped_df['年份'].map({0:'2011', 1:'2012'})
### 绘图
plt.figure(figsize = (14,6))
plt.subplot(1, 2, 1)
plt.bar(count_grouped_df['年份'],
count_grouped_df['使用量'],
width=0.5,
color=['blue', 'orange'])
plt.title('两年使用总量对比条形图', fontsize=15)
plt.xlabel('年份', fontsize=15)
plt.ylabel('使用量', fontsize=15)
## 绘制饼状图
### 计算百分比
count_grouped_df['百分比'] = count_grouped_df['使用量']/count_grouped_df['使用量'].sum()
### 绘图
plt.subplot(1, 2, 2)
plt.pie(count_grouped_df['百分比'],
labels=['2011', '2012'],
autopct = '%1.1f')
plt.title('两年使用总量对比饼状图', fontsize=15)
plt.legend(loc='upper right', fontsize=10)
从上面两幅图可以看出,2012年单车的使用量要远高于2011年的使用量,用户几乎增加了一倍,说明共享单车在这期间的推广比较有成效。
为了探究单车使用量的影响因素,我们首先使用条形图和折线图来探究两年中使用量与季节的关系:
## 绘图
### 分组聚合
season_Aggregated = pd.DataFrame(data.groupby(['年份','季节']).sum())['使用量'].reset_index()
### 绘制条形图
plt.figure(figsize=(14, 8))
plt.subplot(1, 2, 1)
plt.bar(season_Aggregated['季节'][:4]-0.2,
season_Aggregated['使用量'][:4],
width=0.4,
color='green', label='2011')
plt.bar(season_Aggregated['季节'][4:]+0.2,
season_Aggregated['使用量'][4:],
width=0.4,
color='yellow', label='2012')
plt.title('使用量与季节关系条形图', fontsize=15)
plt.xlabel('季节', fontsize=15)
plt.ylabel('使用量', fontsize=15)
plt.xticks([1, 2, 3, 4], ['春季', '夏季', '秋季', '冬季'])
plt.legend(loc='best')
### 绘制折线图
plt.subplot(1, 2, 2)
plt.plot(season_Aggregated['季节'][:4],
season_Aggregated['使用量'][:4],
color='green',
lw=3,
marker='o',
label='2011')
plt.plot(season_Aggregated['季节'][4:],
season_Aggregated['使用量'][4:],
color='yellow',
lw=3,
marker='o',
label='2012')
plt.title('使用量与季节折线图', fontsize=15)
plt.xlabel('季节', fontsize=15)
plt.ylabel('使用量', fontsize=15)
plt.xticks([1, 2, 3, 4], ['春季', '夏季', '秋季', '冬季'])
plt.legend(loc='best')
plt.grid(True)
从上面两幅图可以看出,使用量随季节变化的趋势大致相同,而春季使用量明显少于其它三个季节,秋季使用量需求最大。
为了探究共享单车的使用量和月份之间的关系,我们将使用条形图和折线图来进行可视化。
## 绘图
### 分组聚合
month_Aggregated = pd.DataFrame(data.groupby(['年份','月份']).sum())['使用量'].reset_index()
### 绘制条形图
plt.figure(figsize=(14, 10))
plt.subplot(2, 1, 1)
plt.bar(month_Aggregated['月份'][:12]-0.2,
month_Aggregated['使用量'][:12],
width=0.4,
color='blue', label='2011')
plt.bar(month_Aggregated['月份'][12:]+0.2,
month_Aggregated['使用量'][12:],
width=0.4,
color='gold', label='2012')
plt.title('使用量与月份关系条形图', fontsize=15)
plt.xlabel('月份', fontsize=15)
plt.ylabel('使用量', fontsize=15)
plt.xticks(np.arange(1, 13))
plt.legend(loc='best')
### 绘制折线图
plt.subplot(2, 1, 2)
plt.plot(month_Aggregated['月份'][:12],
month_Aggregated['使用量'][:12],
color='blue',
lw=3,
marker='o',
label='2011')
plt.plot(month_Aggregated['月份'][12:],
month_Aggregated['使用量'][12:],
color='gold',
lw=3,
marker='o',
label='2012')
plt.title('使用量与月份折线图', fontsize=15)
plt.xlabel('月份', fontsize=15)
plt.ylabel('使用量', fontsize=15)
plt.xticks(np.arange(1, 13))
plt.legend(loc='best')
plt.grid(True)
从上面两幅图可以看到,两年中每月的租车量的变化趋势大致相同,租车量的高峰体现在7、8、9月份,可见用户在这三个月对租车需求较大。
为了探究共享单车的使用量和星期几的关系,我们将使用条形图和箱线图进行可视化分析。
条形图将帮助我们直观地比较不同星期的使用量。通过条形的长度或高度,我们可以清晰地看出哪一天的使用量更高或更低。通过这种比较,我们可以发现使用量的周周期性变化,例如是否在工作日或周末的使用量会有所不同。
箱线图则将展示每周使用量的分布情况。通过箱线图,我们可以观察到数据的集中趋势(中位数)、离散程度(四分位距)以及任何可能的异常值。箱线图有助于我们快速识别出数据中的极端值或异常点,这些值可能对数据的整体分布和解读产生影响。
从上面三幅图可以看出,2011年一周内各天的租车量大致相同,2012年周四、周五和周六的租车量最高;在工作日方面,是否为工作日对租车辆的影响并不明显;而节假日的租车量相较非节假日来说较小。
接着,我们使用箱线图来观察使用量与天气的关系:
## 筛选
plt.figure(figsize=(8, 8))
weaType1 = pd.Series(data['使用量'][data['天气类型']==1])
weaType2 = pd.Series(data['使用量'][data['天气类型']==2])
weaType3 = pd.Series(data['使用量'][data['天气类型']==3])
weather_usecount = [weaType1, weaType2, weaType3]
### 箱线图
plt.boxplot(weather_usecount,
labels = ['晴朗少云', '多云雾', '小雨雪雷电'],
widths=0.5,
patch_artist = True,
showfliers = False)
plt.title('使用量与天气关系箱线图', fontsize=15)
plt.xlabel('天气', fontsize=15)
plt.grid(True)
从上图可以看出,天气对租车量的影响较为明显,随着天气质量的逐渐变差,单车使用量逐渐减少。
为了探究共享单车的使用量和温度、湿度、风速之间的关系,我们将使用条形图和折线图进行可视化分析。
单车使用量与温度的关系:
### 与温度的关系
plt.figure(figsize=(12, 8))
ggplot(data, aes('温度', '使用量')) + geom_point(color='blue') + geom_smooth(method='lm') + theme(text = element_text(fontproperties=myfont))
单车使用量与湿度的关系:
### 与湿度的关系
plt.figure(figsize=(12, 8))
ggplot(data, aes('湿度', '使用量')) + geom_point(color='green') + geom_smooth(method='lm') + theme(text = element_text(fontproperties=myfont))
### 与风速的关系
plt.figure(figsize=(12, 8))
ggplot(data, aes('风速', '使用量')) + geom_point(color='red') + geom_smooth(method='lm') + theme(text = element_text(fontproperties=myfont))
从上面三幅图可以看出,温度与使用量呈正相关关系,随着温度的升高租车量在增加;湿度和风速与使用量呈负相关关系,随着湿度和风速的升高租车量在下降。
下面我们把数据分为训练集和测试集,利用除单车使用量之外的所有特征来建立决策树模型,预测单车的使用量,并将模型可视化并得到各特征的重要性,数据的分割比例为训练集75%,测试集25%。
## 分离数据和目标
X = data.drop(['日期', '使用量'], axis=1)
y = data['使用量']
## 分割训练集合测试集
cut_point = np.floor(X.shape[0]*0.75)
### 分割训练集
X_train = X.loc[:cut_point, :]
y_train = y.loc[:cut_point]
### 分割测试集
X_test = X.loc[cut_point:, :]
y_test = y.loc[cut_point:]
接下来,我们建立模型并使用训练集进行训练:
## 载入必要库
from sklearn.tree import DecisionTreeRegressor
### 建立模型
model_DF = DecisionTreeRegressor(max_depth=3, random_state=10)
### 训练模型
model_DF.fit(X_train, y_train)
决策树可视化:
### 决策树可视化
## 导入必要库
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
from IPython.display import Image
import pydotplus
## 输出图片到dot文件
X_train_ename = ['season', 'year', 'month', 'holiday', 'weekday', 'workingday', 'weather', 'temperature', 'humidity', 'windSpend']
export_graphviz(model_DF, out_file='tree.dot',
feature_names=X_train_ename,
rounded=True, precision = 1)
## 使用dot文件构造图
graph= pydotplus.graph_from_dot_file('tree.dot')
Image(graph.create_png())
### 查看特征重要性
feature_importance = pd.Series(model_DF.feature_importances_, index=X_train.columns).sort_values(ascending=False)[:5]
print(feature_importance)
### 绘制水平条形图
plt.figure(figsize=(8, 6))
plt.bar(feature_importance.index,
feature_importance.values,
color=['b', 'k', 'g', 'y', 'm'])
plt.title('特征重要性条形图', fontsize=15)
plt.xlabel('特征', fontsize=15)
plt.ylabel('重要性', fontsize=15)
根据本次共享单车可视化项目的分析,我们得出以下结论: