1.1 项目说明
自行车共享系统是一种租赁自行车的方法,注册会员、租车、还车都将通过城市中的站点网络自动完成,通过这个系统人们可以根据需要从一个地方租赁一辆自行车然后骑到自己的目的地归还。为了更好地服务和维护共享单车平台,开发和运营人员会通过系统记录的数据来研究和优化共享单车平台,挖掘数据有用信息,最后落地优化系统。这些系统生成的数据很有吸引力,骑行时间、出发地点、到达地点和经过的时间都被显式地记录下来。
在这次比赛中,参与者需要结合历史天气数据下的使用模式,来预测D.C.华盛顿首都自行车共享项目的自行车租赁需求。
1.2 变量说明
datetime(日期) - hourly date + timestamp
season(季节) - 1 = spring, 2 = summer, 3 = fall, 4 = winter
holiday(是否假日) - whether the day is considered a holiday
workingday(是否工作日) - whether the day is neither a weekend nor holiday
weather(天气等级) -
1. 清澈,少云,多云。
2. 雾+阴天,雾+碎云、雾+少云、雾
3. 小雪、小雨+雷暴+散云,小雨+云
4. 暴雨+冰雹+雷暴+雾,雪+雾
temp(温度) - temperature in Celsius
atemp(体感温度) - "feels like" temperature in Celsius
humidity(相对湿度) - relative humidity
windspeed(风速) - wind speed
casual(临时租赁数量) - number of non-registered user rentals initiated
registered(会员租赁数量) - number of registered user rentals initiated
count(总租赁数量) - number of total rentals
2.准备数据:
2.1检查缺失值
%matplotlib inline
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns
train=pd.read_csv('train.csv')
#查看训练集数据是否有缺失值
train.info()
输出
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10886 entries, 0 to 10885
Data columns (total 12 columns):
datetime 10886 non-null object
season 10886 non-null int64
holiday 10886 non-null int64
workingday 10886 non-null int64
weather 10886 non-null int64
temp 10886 non-null float64
atemp 10886 non-null float64
humidity 10886 non-null int64
windspeed 10886 non-null float64
casual 10886 non-null int64
registered 10886 non-null int64
count 10886 non-null int64
dtypes: float64(3), int64(8), object(1)
memory usage: 1020.6+ KB
#查看测试集数据是否有缺失值
test=pd.read_csv('test.csv')
test.info()
输出
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6493 entries, 0 to 6492
Data columns (total 9 columns):
datetime 6493 non-null object
season 6493 non-null int64
holiday 6493 non-null int64
workingday 6493 non-null int64
weather 6493 non-null int64
temp 6493 non-null float64
atemp 6493 non-null float64
humidity 6493 non-null int64
windspeed 6493 non-null float64
dtypes: float64(3), int64(5), object(1)
memory usage: 456.6+ KB
本数据集没有缺失数据,但没有缺失不代表没有异常
2.2将训练数据集与测试数据集合并(方便对数据进行统一预处理)
#进行中文转换
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['font.serif'] = ['SimHei']
import seaborn as sns
sns.set_style("darkgrid",{"font.sans-serif":['simhei', 'Arial']})
dataset=pd.concat([train,test],axis=0)
dataset.isnull().sum()
输出
atemp 0
casual 6493
count 6493
datetime 0
holiday 0
humidity 0
registered 6493
season 0
temp 0
weather 0
windspeed 0
workingday 0
dtype: int64
三个目标变量存在缺失值,且数量与测试数据集一致,因此能判断数据较完整无缺失情况,缺失的只是需要预测的那一部分目标变量。将超过样本均值3个标注差以外的数据看作异常值,本文对异常情况暂不处理。
将量化的特征转换为方便识别和可视化的字段
# season特征 & weather特征
dataset['season']=dataset['season'].map({1:'spring',2:'summer',3:'fall',4:'winter'})
dataset['weather']=dataset['weather'].map({1:'Good',2:'Normal',3:'Bad',4:'Ver Bad'})
将被量化的季节特征和天气特征转化为用字符串描述的数据。
3 特征衍生
为了更好地理解数据,分析前我们需要判断能否从数据已有的特征中提取、构建出某些有价值的特征,这就是衍生特征。
在本篇分析的数据中,我们能对时间数据datetime做特征衍生,datetime包含了日期和时间信息,从中我们能提取出年、月、日、小时等信息。
# 特征衍生
dataset['datetime']=pd.to_datetime(dataset['datetime']) # 将datetime字段转换为datetime
dataset['year']=dataset.datetime.apply(lambda d:d.year) # 对datetime调用year提取年
dataset['month']=dataset.datetime.apply(lambda d:d.month) # 对datetime调用month提取月
dataset['day']=dataset.datetime.apply(lambda d:d.day) # 对datetime调用day提取日
dataset['hour']=dataset.datetime.apply(lambda d:d.hour) # 对datetime调用hour提取小时
# 删除无用字段
dataset.drop('datetime',axis=1,inplace=True)
![3ca2957b70241672a7517620396649d5.png](https://i-blog.csdnimg.cn/blog_migrate/7f5186ec684fe394cadec10fa488c61c.jpeg)
4 可视化分析
通过Matplotlib、Seaborn等工具可视化理解数据,分析特征与标签之间的相关性。
4.1 标签特征的整体分布
count(数量)为本次分析的标签特征,我们需要围绕此特征做可视化分析。下图是count的核密度图:可见count分布呈右偏状,主要集中在0~400这个区间。
![b04e6e3921e66462a37bafd4fe5caf5b.png](https://i-blog.csdnimg.cn/blog_migrate/27005b3fba8875c31fa746930e91ad60.jpeg)
4.2 时间维度看需求趋势
月份维度
数据涵括了两年的跨度,因此按年分开绘制每个月的骑行需求趋势图
# 筛选提取出2011年和2012年的骑行好数据
Month_tendency_2011=dataset[dataset.year==2011].groupby('month')[['casual','registered','count']].sum()
Month_tendency_2012=dataset[dataset.year==2012].groupby('month')[['casual','registered','count']].sum()
# 绘制图像
plt.style.use('ggplot')
fig,[ax1,ax2]=plt.subplots(2,1,figsize=(12,15))
plt.subplots_adjust(hspace=0.3)
Month_tendency_2011.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',ax=ax1)
ax1.set_title('2011年需求趋势',fontsize=15)
ax1.grid(linestyle='--',alpha=0.8)
ax1.set_ylim(0,150000)
ax1.set_xlabel('月份',fontsize=13)
ax1.set_ylabel('数量',fontsize=13)
Month_tendency_2012.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',ax=ax2)
ax2.set_title('2012年需求趋势',fontsize=15)
ax2.grid(linestyle='--',alpha=0.8)
ax2.set_ylim(0,150000)
ax2.set_xlabel('月份',fontsize=13)
ax2.set_ylabel('数量',fontsize=13)
sns.despine(left=True)
![1ac38f3af8b8cc5aaa988f5552dc0919.png](https://i-blog.csdnimg.cn/blog_migrate/6ef612b64f257d9c49c7928548f5cb8a.jpeg)
上图为可视化结果,整体上可见2012年相较于2011年,骑行的需求有了大幅的增长。总需求和注册用户需求的变化最为明显,而非注册用户提升效果一般,这说明:经过一年的运营,越来越多的使用者在平台上注册了,注册用户提升显著。从月份角度,我们能看到的是:6月~9月是骑行旺季,12月~2月是骑行淡季。
小时维度
按照一天24小时可视化骑行需求,我们能发现一些有趣的结论:
# 提取出每小时的骑行需求均值
Hour_tendency=dataset.groupby('hour')[['casual','registered','count']].mean()
# 绘制图像
Hour_tendency.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',figsize=(12,6))
plt.title('小时需求趋势',fontsize=15)
plt.grid(linestyle='--',alpha=0.8)
plt.ylim(0,550)
plt.xlabel('小时',fontsize=13)
plt.ylabel('数量',fontsize=13)
sns.despine(left=True)
![7323d4dc11af932885961ed3053dfbcc.png](https://i-blog.csdnimg.cn/blog_migrate/cd626e6b73a8a16acc3e6a6d0a19cb3c.jpeg)
从24小时观察骑行需求:存在6~7AM以及5~6PM两个峰值,中午12AM有一个小峰值,符合通勤规律,注册用户特征更为明显,而非注册用户则变化平缓。
工作日和非工作日的小时维度
plt.style.use('ggplot')
plt.figure(figsize=(12,6))
sns.pointplot(x='hour',y='count',hue='workingday',data=dataset,ci=None,palette='Spectral')
sns.despine(left=True)
plt.xlabel('小时',fontsize=13)
plt.ylabel('数量',fontsize=13)
plt.grid(linestyle='--',alpha=0.5)
plt.title('工作日/假期 需求趋势',fontsize=15) # 标题设置
![e40096674b10a2c350425863d7bded0f.png](https://i-blog.csdnimg.cn/blog_migrate/a0359702c964a617fa075c6d21cf6312.jpeg)
可见工作日与非工作日的骑行需求规律反差巨大,非工作日的共享单车苏醒慢,骑行需求高峰出现在12AM~3PM的这段时间内,另外凌晨0AM~4AM的骑行需求大于工作日。
不同季节的小时维度
plt.figure(figsize=(12,6))
sns.pointplot(x='hour',y='count',hue='season',data=dataset,ci=None,palette='Spectral')
sns.despine(left=True)
plt.xlabel('小时',fontsize=13)
plt.ylabel('数量',fontsize=13)
plt.grid(linestyle='--',alpha=0.5)
plt.title('季节需求趋势',fontsize=15)
![e12385199212b24574b6c4f5d6c611c9.png](https://i-blog.csdnimg.cn/blog_migrate/2b91183d380bd97959452a15481b71b5.jpeg)
春夏秋冬四季24小时需求趋势一致,值得关注的是春季的整体小于夏秋冬三个季节,体感舒适度最高的秋天整体骑行需求最高。为何春季需求会低于其他季节?这是个值得思考的问题,单限于数据信息有限,未找出合理的解释。这也说明了结合业务的重要性,只有深入了解了业务规律才能做出准确判断。
4.3 天气维度
不同天气、气温等外在环境会影响骑行需求。
不同天气状况的骑行需求
# 将数据按天聚合
Weather_Demand=dataset.groupby(['weather','day'])[['count']].sum()
Weather_Demand.reset_index(inplace=True)
# 不同天气的骑行需求散点图
plt.figure(figsize=(12,6))
sns.stripplot(x='weather',y='count',data=Weather_Demand,palette='Set1',jitter=True,alpha=0.6)
sns.despine(left=True)
plt.xlabel('季节',fontsize=13)
plt.ylabel('数量',fontsize=13)
plt.title('天气的分布趋势',fontsize=15)
![00a05e1661e54292bb22d94019e9d19c.png](https://i-blog.csdnimg.cn/blog_migrate/18a193a51cf93ac1a9aeaa5b5c56d16d.jpeg)
可见,天气情况越糟,骑行需求越小。
# 不同天气的骑行需求趋势
plt.figure(figsize=(12,6))
sns.pointplot(x='hour',y='count',hue='weather',data=dataset,ci=None,palette='Spectral')
sns.despine(left=True)
plt.xlabel('小时',fontsize=13)
plt.ylabel('数量',fontsize=13)
plt.grid(linestyle='--',alpha=0.5)
plt.title('天气的需求趋势',fontsize=15)
![ab49141217e143cdce93f8c0e1d29b55.png](https://i-blog.csdnimg.cn/blog_migrate/28a71125f1ba2ca69a0baef00c1610f9.jpeg)
整体需求趋势也印证了,天气越差骑行需求越少,极端天气未形成趋势线,极端情况还是占少数的。
气温与体表温度
气温与体表温度应该是正相关的,先来看看两者的分布图:
# 温度与体表温度的关系度量
plt.figure(figsize=(10,8))
sns.kdeplot(dataset['temp'],dataset['atemp'],shade=True,shade_lowest=False,cut=10,cmap='YlGnBu',cbar=True)
sns.despine(left=True)
plt.grid(linestyle='--',alpha=0.4)
plt.xlim(0,50)
plt.ylim(0,50)
plt.xlabel('温度',fontsize=13)
plt.ylabel('体表温度',fontsize=13)
plt.title('温度和体表温度的相关性',fontsize=15)
![7b2de32b7750a61ced72ab3f845de6b9.png](https://i-blog.csdnimg.cn/blog_migrate/0d3f1fe927182d63ed0fcd7cbaa40c1f.jpeg)
从两者的关系度量图中我们能看出呈现正相关分布,另外能获取到的信息是:颜色最深的分布最为集中,最适宜的气温27℃~28℃、体表温度31℃左右的骑行需求是最密集的。
# 温度与风速的关系度量
plt.figure(figsize=(10,8))
sns.kdeplot(dataset['temp'],dataset['windspeed'],shade=True,shade_lowest=False,cut=10,cmap='YlGnBu',cbar=True)
sns.despine(left=True)
plt.grid(linestyle='--',alpha=0.4)
plt.xlim(0,50)
plt.ylim(-10,40)
plt.xlabel('温度',fontsize=13)
plt.ylabel('风速',fontsize=13)
plt.title('温度和风速的相关性',fontsize=15)
![06ab6c58427e223e137589a7d847f699.png](https://i-blog.csdnimg.cn/blog_migrate/af62fbb25d951c15e626a607c40a3385.jpeg)
风速的分布存在断层,初步推断可能是异常数据,这里先不做处理;可见气温27℃~28℃,风速8~9骑行需求是最密集的。
气温与湿度
# 温度与湿度的关系度量
plt.figure(figsize=(10,8))
sns.kdeplot(dataset['temp'],dataset['humidity'],shade=True,shade_lowest=False,cut=10,cmap='YlGnBu',cbar=True)
sns.despine(left=True)
plt.grid(linestyle='--',alpha=0.4)
plt.xlim(0,40)
plt.ylim(0,110)
plt.xlabel('温度',fontsize=13)
plt.ylabel('湿度',fontsize=13)
plt.title('温度和湿度的相关性',fontsize=15)
![f3032ffa3de464cc281d97b97275add8.png](https://i-blog.csdnimg.cn/blog_migrate/12601a7856c3553d72e6e1eea36bf0eb.jpeg)
气温27℃~28℃,湿度80~90骑行需求是最密集的。
天气因素与骑行需求
将气温和风速作为天气因素分析骑行需求(忽略体表温度,气温即代表了体表温度),使用散点图绘制,散点的大小和颜色代表了骑行量,每个散点代表一天。
plt.figure(figsize=(12,6))
plt.scatter(x='temp',y='windspeed',
s=dataset['count']/2,
c='count',cmap='RdBu_r',
edgecolors='black',linestyle='--',linewidth=0.2,alpha=0.6,
data=dataset)
plt.title('天气因素与骑行需求',fontsize=15)
plt.xlabel('温度',fontsize=13)
plt.ylabel('风速',fontsize=13)
sns.despine(left=True)
![4c9fdca48f53dbc24e80cadb19dde2c1.png](https://i-blog.csdnimg.cn/blog_migrate/a32a02416a6dc9dcccba03c4dfce6783.jpeg)
可见骑行需求较多的分布范围:气温20℃~35℃,风速40以下;人们更热衷于温暖天气骑行,炎热天气需求也大的原因可能是因为相对于公共交通,骑行更加灵活方便吧。
将气温和湿度作为天气因素分析骑行需求:
plt.figure(figsize=(12,6))
plt.scatter(x='temp',y='humidity',
s=dataset['count']/2,
c='count',cmap='RdBu_r',
edgecolors='black',linestyle='--',linewidth=0.2,alpha=0.6,
data=dataset)
plt.title('天气因素与骑行需求',fontsize=15)
plt.xlabel('温度',fontsize=13)
plt.ylabel('湿度',fontsize=13)
sns.despine(left=True)
![8bea48d38ac4682ec7bebd2aaccc5f4f.png](https://i-blog.csdnimg.cn/blog_migrate/d2e04a340ce4e9065de5921cc71dfec6.jpeg)
可见骑行需求较多的分布范围:气温20℃~35℃,湿度20~80。
4.5 注册用户与未注册用户
如何能提升平台用户数量?当然是拉新促活促转化,接下来,让我们来观察下注册用户与非注册用户的差异吧。
# 衍生特征
dataset['dif']=dataset['registered']-dataset['casual'] # 衍生特征注册用户与非注册用户的骑行需求差值
fig,axes=plt.subplots(2,2,figsize=(20,8))
plt.subplots_adjust(hspace=0.3,wspace=0.1)
# 绘制子图1:月度差异
Month_Dif = dataset.groupby('month')[['casual','registered']].mean()
Month_Dif.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',ax=axes[0,0])
axes[0,0].set_title('月份趋势需求差异',fontsize=15)
axes[0,0].grid(linestyle='--',alpha=0.8)
axes[0,0].set_xlabel('月份',fontsize=13)
axes[0,0].set_ylabel('数量',fontsize=13)
# 绘制子图2:小时差异
H1=dataset.groupby('hour')[['casual','registered']].mean()
H1.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',ax=axes[0,1])
axes[0,1].set_title('小时趋势需求差异',fontsize=15)
axes[0,1].grid(linestyle='--',alpha=0.8)
axes[0,1].set_xlabel('小时',fontsize=13)
axes[0,1].set_ylabel('数量',fontsize=13)
# 绘制子图3:工作日差异
H2_1=dataset[dataset.workingday==1].groupby('hour')[['casual','registered']].mean() # 工作日
H2_0=dataset[dataset.workingday==0].groupby('hour')[['casual','registered']].mean() # 非工作日
H2_1.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',ax=axes[1,0])
axes[1,0].set_title('工作日时间趋势需求差异',fontsize=15)
axes[1,0].grid(linestyle='--',alpha=0.8)
axes[1,0].set_xlabel('小时',fontsize=13)
axes[1,0].set_ylabel('数量',fontsize=13)
# 绘制子图4:非工作日差异
H2_0.plot(kind='line',linestyle='--',linewidth=2,colormap='Set1',ax=axes[1,1])
axes[1,1].set_title('假期时间趋势需求差异',fontsize=15)
axes[1,1].grid(linestyle='--',alpha=0.8)
axes[1,1].set_xlabel('小时',fontsize=13)
axes[1,1].set_ylabel('数量',fontsize=13)
sns.despine(left=True)
![0ae82a079ba6ef51f74cd63d08d4780b.png](https://i-blog.csdnimg.cn/blog_migrate/8ab975c5304f23d9093117610cae02c0.jpeg)
上图为注册用户与非注册用户在各因素下的差异组合图:
第一幅为两者的月度差异图,可见整体趋势相同,注册用户远高于非注册用户;
第二幅为两者的小时差异图,可见注册用户的小时规律明显,非注册用户则只在12AM~5PM存在峰值,整体差异较大;
第三幅为两者的工作日差异图,可见注册用户工作日小时规律明显,二非注册用户趋势平缓;
第四幅为两者的非工作日差异图,可见非工作日两者差异相较于其他因素差异较小,且趋势相同,值得注意的是注册用户在凌晨更加活跃。
总的来说,注册用户需求远高于非注册用户,注册用户的使用规律明显,而非注册用户受其他因素的影响相对较弱。