温州做网站建设哪家好,企业微信网页版,盐山网站建设,网站设计所需要的理念文章目录一、数据收集1.1、项目说明1.2、数据内容及变量说明二、数据处理2.1、导入数据2.2、缺失值处理2.3、Label数据(即count)异常值处理2.4、其他数据异常值处理2.5、时间型数据数据处理三、数据分析3.1 描述性分析3.2、探索性分析3.2.1、整体性分析3.2.2、相关性分析3.2.3、…
文章目录一、数据收集1.1、项目说明1.2、数据内容及变量说明二、数据处理2.1、导入数据2.2、缺失值处理2.3、Label数据(即count)异常值处理2.4、其他数据异常值处理2.5、时间型数据数据处理三、数据分析3.1 描述性分析3.2、探索性分析3.2.1、整体性分析3.2.2、相关性分析3.2.3、影响因素分析3.2.3.1、时段对租赁数量的影响3.2.3.2、温度对租赁数量的影响3.2.3.3、 湿度对租赁数量的影响3.2.3.4、年份、月份对租赁数量的影响3.2.3.5、季节对出行人数的影响3.2.3.6、天气情况对出行情况的影响3.2.3.7、风速对出行情况的影响3.2.3.8、日期对出行的影响3.3、预测性分析3.3.1、选择特征值3.3.2、训练集、测试集分离3.3.3、多余特征值舍弃3.3.4、选择模型、训练模型3.3.5、预测测试集数据一、数据收集
1.1、项目说明
自行车共享系统是一种租赁自行车的方法注册会员、租车、还车都将通过城市中的站点网络自动完成通过这个系统人们可以根据需要从一个地方租赁一辆自行车然后骑到自己的目的地归还。在这次比赛中参与者需要结合历史天气数据下的使用模式来预测D.C.华盛顿首都自行车共享项目的自行车租赁需求。
1.2、数据内容及变量说明
比赛提供了跨越两年的每小时租赁数据包含天气信息和日期信息训练集由每月前19天的数据组成测试集是每月第二十天到当月底的数据。
二、数据处理
2.1、导入数据
import matplotlib.pyplot as pltimport seaborn as sns
sns.set(stylewhitegrid , palettetab10)trainpd.read_csv(rD:\A\Data\ufo\train.csv,encodingutf-8)
train.info()testpd.read_csv(rD:\A\Data\ufo\test.csv,encodingutf-8)
print(test.info()) 2.2、缺失值处理
#可视化查询缺失值
import missingno as msno
msno.matrix(train,figsize(12,5))
msno.matrix(test,figsize(12,5)) 本次数据没有缺失值不需要进行缺失值处理。
2.3、Label数据(即count)异常值处理
#观察训练集数据描述统计
train.describe().T 先从数值型数据入手可以看出租赁额count数值差异大再观察一下它们的密度分布
#观察租赁额密度分布
fig plt.figure()
ax fig.add_subplot(1, 1, 1)
fig.set_size_inches(6,5)sns.distplot(train[count])
ax.set(xlabelcount,titleDistribution of count,) 发现数据密度分布的偏斜比较严重且有一个很长的尾所以希望能把这一列数据的长尾处理一下先排除掉3个标准差以外的数据试一下能不能满足要求
train_WithoutOutliers train[np.abs(train[count]-train[count].mean())(3*train[count].std())]
print(train_WithoutOutliers.shape)
train_WithoutOutliers[count] .describe() 与处理前对比不是很明显可视化展示对比看一下
fig plt.figure()
ax1 fig.add_subplot(1, 2, 1)
ax2 fig.add_subplot(1, 2, 2)
fig.set_size_inches(12,5)sns.distplot(train_WithoutOutliers[count],axax1)
sns.distplot(train[count],axax2)ax1.set(xlabelcount,titleDistribution of count without outliers,)
ax2.set(xlabelregistered,titleDistribution of count) 可以看到数据波动依然很大而我们希望波动相对稳定否则容易产生过拟合所以希望对数据进行处理使得数据相对稳定此处选择对数变化来使得数据稳定。
yLabelstrain_WithoutOutliers[count]
yLabels_lognp.log(yLabels)
sns.distplot(yLabels_log) 经过对数变换后数据分布更均匀大小差异也缩小了使用这样的标签对训练模型是有效果的。接下来对其余的数值型数据进行处理由于其他数据同时包含在两个数据集中为方便数据处理先将两个数据集合并。
Bike_datapd.concat([train_WithoutOutliers,test],ignore_indexTrue)
#查看数据集大小
Bike_data.shape 2.4、其他数据异常值处理
fig, axes plt.subplots(2, 2)
fig.set_size_inches(12,10)sns.distplot(Bike_data[temp],axaxes[0,0])
sns.distplot(Bike_data[atemp],axaxes[0,1])
sns.distplot(Bike_data[humidity],axaxes[1,0])
sns.distplot(Bike_data[windspeed],axaxes[1,1])axes[0,0].set(xlabeltemp,titleDistribution of temp,)
axes[0,1].set(xlabelatemp,titleDistribution of atemp)
axes[1,0].set(xlabelhumidity,titleDistribution of humidity)
axes[1,1].set(xlabelwindspeed,titleDistribution of windspeed) 通过这个分布可以发现一些问题比如风速为什么0的数据很多而观察统计描述发现空缺值在1–6之间从这里似乎可以推测数据本身或许是有缺失值的但是用0来填充了但这些风速为0的数据会对预测产生干扰希望使用随机森林根据相同的年份月份季节温度湿度等几个特征来填充一下风速的缺失值。填充之前看一下非零数据的描述统计。
Bike_data[Bike_data[windspeed]!0][windspeed].describe() from sklearn.ensemble import RandomForestRegressorBike_data[windspeed_rfr]Bike_data[windspeed]
# 将数据分成风速等于0和不等于两部分
dataWind0 Bike_data[Bike_data[windspeed_rfr]0]
dataWindNot0 Bike_data[Bike_data[windspeed_rfr]!0]
#选定模型
rfModel_wind RandomForestRegressor(n_estimators1000,random_state42)
# 选定特征值
windColumns [season,weather,humidity,month,temp,year,atemp]
# 将风速不等于0的数据作为训练集fit到RandomForestRegressor之中
rfModel_wind.fit(dataWindNot0[windColumns], dataWindNot0[windspeed_rfr])
# 通过训练好的模型预测风速
wind0Values rfModel_wind.predict(X dataWind0[windColumns])
#将预测的风速填充到风速为零的数据中
dataWind0.loc[:,windspeed_rfr] wind0Values
#连接两部分数据
Bike_data dataWindNot0.append(dataWind0)
Bike_data.reset_index(inplaceTrue)
Bike_data.drop(index,inplaceTrue,axis1)
观察随机森林填充后的密度分布情况
fig, axes plt.subplots(2, 2)
fig.set_size_inches(12,10)sns.distplot(Bike_data[temp],axaxes[0,0])
sns.distplot(Bike_data[atemp],axaxes[0,1])
sns.distplot(Bike_data[humidity],axaxes[1,0])
sns.distplot(Bike_data[windspeed_rfr],axaxes[1,1])axes[0,0].set(xlabeltemp,titleDistribution of temp,)
axes[0,1].set(xlabelatemp,titleDistribution of atemp)
axes[1,0].set(xlabelhumidity,titleDistribution of humidity)
axes[1,1].set(xlabelwindseed,titleDistribution of windspeed) 2.5、时间型数据数据处理
Bike_data[date]Bike_data.datetime.apply( lambda c : c.split( )[0])
Bike_data[hour]Bike_data.datetime.apply( lambda c : c.split( )[1].split(:)[0]).astype(int)
Bike_data[year]Bike_data.datetime.apply( lambda c : c.split( )[0].split(/)[0]).astype(int)
Bike_data[month]Bike_data.datetime.apply( lambda c : c.split( )[0].split(/)[1]).astype(int)
Bike_data[weekday]Bike_data.date.apply( lambda c : datetime.strptime(c,%Y/%m/%d).isoweekday())
Bike_data.head() 三、数据分析
3.1 描述性分析
train.describe().T 温度, 体表温度, 相对湿度, 风速均近似对称分布, 而非注册用户, 注册用户,以及总数均右边分布。
for i in range(5, 12):name train.columns[i]print({0}偏态系数为 {1}, 峰态系数为 {2}.format(name, train[name].skew(), train[name].kurt())) temp, atemp, humidity低度偏态, windspeed中度偏态, casual, registered, count高度偏态 temp, atemp, humidity为平峰分布, windspeed,casual, registered, count为尖峰分布。
3.2、探索性分析
3.2.1、整体性分析
sns.pairplot(Bike_data ,x_vars[holiday,workingday,weather,season,weekday,hour,windspeed_rfr,humidity,temp,atemp] ,y_vars[casual,registered,count] , plot_kws{alpha: 0.1}) 大致可以看出
会员在工作日出行多节假日出行少临时用户则相反一季度出行人数总体偏少租赁数量随天气等级上升而减少小时数对租赁情况影响明显会员呈现两个高峰非会员呈现一个正态分布租赁数量随风速增大而减少温度、湿度对非会员影响比较大对会员影响较小。
3.2.2、相关性分析
查看各个特征与每小时租车总量count的相关性
correlation Bike_data.corr()
mask np.array(correlation)
mask[np.tril_indices_from(mask)] False
fig,ax plt.subplots()
fig.set_size_inches(20,10)
sns.heatmap(correlation, maskmask,vmax.8, squareTrue,annotTrue)plt.show() count 和 registered、casual高度正相关相关系数分别为0.7 与0.97。因为 count casual registered 所以这个正相关和预期相符。count 和 temp 正相关相关系数为 0.39。一般来说气温过低人们不愿意骑车出行。count 和 humidity湿度负相关湿度过大的天气不适宜骑车。当然考虑湿度的同时也应该考虑温度。windspeed似乎对租车人数影响不大0.1但我们也应该考虑到极端大风天气出现频率应该不高。风速在正常范围内波动应该对人们租车影响不大。可以看出特征值对租赁数量的影响力度为,时段温度湿度年份月份季节天气等级风速星期几是否工作日是否假日
3.2.3、影响因素分析
3.2.3.1、时段对租赁数量的影响
workingday_dfBike_data[Bike_data[workingday]1]
workingday_df workingday_df.groupby([hour], as_indexTrue).agg({casual:mean,registered:mean,count:mean})nworkingday_dfBike_data[Bike_data[workingday]0]
nworkingday_df nworkingday_df.groupby([hour], as_indexTrue).agg({casual:mean,registered:mean, count:mean})
fig, axes plt.subplots(1, 2,sharey True)workingday_df.plot(figsize(15,5),title The average number of rentals initiated per hour in the working day,axaxes[0])
nworkingday_df.plot(figsize(15,5),title The average number of rentals initiated per hour in the nonworkdays,axaxes[1]) 通过对比可以看出
工作日对于会员用户上下班时间是两个用车高峰而中午也会有一个小高峰猜测可能是外出午餐的人而对临时用户起伏比较平缓高峰期在17点左右并且会员用户的用车数量远超过临时用户。对非工作日而言租赁数量随时间呈现一个正态分布高峰在14点左右低谷在4点左右且分布比较均匀。
3.2.3.2、温度对租赁数量的影响
先观察温度的走势
#数据按小时统计展示起来太麻烦希望能够按天汇总取一天的气温中位数
temp_df Bike_data.groupby([date,weekday], as_indexFalse).agg({year:mean,month:mean,temp:median})#由于测试数据集中没有租赁信息会导致折线图有断裂所以将缺失的数据丢弃
temp_df.dropna ( axis 0 , how any, inplace True )
#预计按天统计的波动仍然很大再按月取日平均值
temp_month temp_df.groupby([year,month], as_indexFalse).agg({weekday:min,temp:median})
#将按天求和统计数据的日期转换成datetime格式
temp_df[date]pd.to_datetime(temp_df[date])#将按月统计数据设置一列时间序列
temp_month.rename(columns{weekday:day},inplaceTrue)
temp_month[date]pd.to_datetime(temp_month[[year,month,day]])#设置画框尺寸
fig plt.figure(figsize(18,6))
ax fig.add_subplot(1,1,1)#使用折线图展示总体租赁情况count随时间的走势
plt.plot(temp_df[date] , temp_df[temp] , linewidth1.3 , labelDaily average)
ax.set_title(Change trend of average temperature per day in two years)
plt.plot(temp_month[date] , temp_month[temp] , markero, linewidth1.3 ,labelMonthly average)
ax.legend() 可以看出每年的气温趋势相同随月份变化在7月份气温最高1月份气温最低再看一下每小时平均租赁数量随温度变化的趋势。
#按温度取租赁额平均值
temp_rentals Bike_data.groupby([temp], as_indexTrue).agg({casual:mean, registered:mean,count:mean})
temp_rentals .plot(title The average number of rentals initiated per hour changes with the temperature) 可观察到随气温上升租车数量总体呈现上升趋势但在气温超过35时开始下降在气温4度时达到最低点。
3.2.3.3、 湿度对租赁数量的影响
先观察湿度的走势
4humidity_df Bike_data.groupby(date, as_indexFalse).agg({humidity:mean})
humidity_df[date]pd.to_datetime(humidity_df[date])
#将日期设置为时间索引
humidity_dfhumidity_df.set_index(date)humidity_month Bike_data.groupby([year,month], as_indexFalse).agg({weekday:min,humidity:mean})
humidity_month.rename(columns{weekday:day},inplaceTrue)
humidity_month[date]pd.to_datetime(humidity_month[[year,month,day]])fig plt.figure(figsize(18,6))
ax fig.add_subplot(1,1,1)
plt.plot(humidity_df.index , humidity_df[humidity] , linewidth1.3,labelDaily average)
plt.plot(humidity_month[date], humidity_month[humidity] ,markero, linewidth1.3,labelMonthly average)
ax.legend()
ax.set_title(Change trend of average humidity per day in two years) 湿度的变化幅度不是很大多数围绕60上下浮动本次数据范围内峰值为80。
humidity_rentals Bike_data.groupby([humidity], as_indexTrue).agg({casual:mean,registered:mean,count:mean})
humidity_rentals .plot (title Average number of rentals initiated per hour in different humidity) 可以观察到在湿度20左右租赁数量迅速达到高峰值此后缓慢递减。
3.2.3.4、年份、月份对租赁数量的影响
观察两年时间里总租车数量随时间变化的趋势
#数据按小时统计展示起来太麻烦希望能够按天汇总
count_df Bike_data.groupby([date,weekday], as_indexFalse).agg({year:mean,month:mean,casual:sum,registered:sum,count:sum})
#由于测试数据集中没有租赁信息会导致折线图有断裂所以将缺失的数据丢弃
count_df.dropna ( axis 0 , how any, inplace True )#预计按天统计的波动仍然很大再按月取日平均值
count_month count_df.groupby([year,month], as_indexFalse).agg({weekday:min,casual:mean, registered:mean,count:mean})#将按天求和统计数据的日期转换成datetime格式
count_df[date]pd.to_datetime(count_df[date])#将按月统计数据设置一列时间序列
count_month.rename(columns{weekday:day},inplaceTrue)
count_month[date]pd.to_datetime(count_month[[year,month,day]])#设置画框尺寸
fig plt.figure(figsize(18,6))
ax fig.add_subplot(1,1,1)#使用折线图展示总体租赁情况count随时间的走势
plt.plot(count_df[date] , count_df[count] , linewidth1.3 , labelDaily average)
ax.set_title(Change trend of average number of rentals initiated per day in two years)
plt.plot(count_month[date] , count_month[count] , markero, linewidth1.3 , labelMonthly average)
ax.legend() 可以看出
共享单车的租赁情况2012年整体是比2011年有增涨的租赁情况随月份波动明显数据在2011年9到12月2012年3到9月间波动剧烈有很多局部波谷值。
3.2.3.5、季节对出行人数的影响
在对年份月份因素的数据分析图中发现存在很多局部低谷所以将租赁数量按季节取中位数展示同时观察季节的温度变化
day_dfBike_data.groupby(date).agg({year:mean,season:mean,casual:sum, registered:sum,count:sum,temp:mean,atemp:mean})season_df day_df.groupby([year,season], as_indexTrue).agg({casual:mean, registered:mean,count:mean})season_df .plot(figsize(18,6),title The trend of average number of rentals initiated per day changes with season) temp_df day_df.groupby([year,season], as_indexTrue).agg({temp:mean, atemp:mean})
temp_df.plot(figsize(18,6),title The trend of average temperature per day changes with season) 可以看出无论是临时用户还是会员用户用车的数量都在秋季迎来高峰而春季度用户数量最低。
3.2.3.6、天气情况对出行情况的影响
考虑到不同天气的天数不同例如非常糟糕的天气4会很少出现查看一下不同天气等级的数据条数再对租赁数量按天气等级取每小时平均值。
count_weather Bike_data.groupby(weather)
count_weather[[casual,registered,count]].count() weather_df Bike_data.groupby(weather, as_indexTrue).agg({casual:mean,registered:mean})
weather_df.plot.bar(stackedTrue,title Average number of rentals initiated per hour in different weather) 此处存在不合理数据天气等级4的时候出行人数并不少尤其是会员出行人数甚至比天气等级2的平均值还高按理说4等级的应该是最少的将天气等级4的数据打印出来找一下原因
Bike_data[Bike_data[weather]4] 观察可知该数据是在上下班高峰期产生的所以该数据是个异常数据。不具有代表性。
3.2.3.7、风速对出行情况的影响
两年时间内风速的变化趋势
windspeed_df Bike_data.groupby(date, as_indexFalse).agg({windspeed_rfr:mean})
windspeed_df[date]pd.to_datetime(windspeed_df[date])
#将日期设置为时间索引
windspeed_dfwindspeed_df.set_index(date)windspeed_month Bike_data.groupby([year,month], as_indexFalse).agg({weekday:min,windspeed_rfr:mean})
windspeed_month.rename(columns{weekday:day},inplaceTrue)
windspeed_month[date]pd.to_datetime(windspeed_month[[year,month,day]])fig plt.figure(figsize(18,6))
ax fig.add_subplot(1,1,1)
plt.plot(windspeed_df.index , windspeed_df[windspeed_rfr] , linewidth1.3,labelDaily average)
plt.plot(windspeed_month[date], windspeed_month[windspeed_rfr] ,markero, linewidth1.3,labelMonthly average)
ax.legend()
ax.set_title(Change trend of average number of windspeed per day in two years) 可以看出风速在2011年9月份和2011年12月到2012年3月份间波动和大观察一下租赁人数随风速变化趋势考虑到风速特别大的时候很少如果取平均值会出现异常所以按风速对租赁数量取最大值。 windspeed_rentals Bike_data.groupby([windspeed], as_indexTrue).agg({casual:max, registered:max,count:max})
windspeed_rentals .plot(title Max number of rentals initiated per hour in different windspeed) 可以看到租赁数量随风速越大租赁数量越少在风速超过30的时候明显减少但风速在风速40左右却有一次反弹打印数据找一下反弹原因
df2Bike_data[Bike_data[windspeed]40]
df2df2[df2[count]400]
df2 该条数据产生在上下班高峰期时期所以也是个异常值不具有代表性。
3.2.3.8、日期对出行的影响
考虑到相同日期是否工作日星期几以及所属年份等信息是一样的把租赁数据按天求和其它日期类数据取平均值 day_df Bike_data.groupby([date], as_indexFalse).agg({casual:sum,registered:sum,count:sum, workingday:mean,weekday:mean,holiday:mean,year:mean})
day_df.head() 6number_peiday_df[[casual,registered]].mean()
number_pei plt.axes(aspectequal)
plt.pie(number_pei, labels[casual,registered], autopct%1.1f%%, pctdistance0.6 , labeldistance1.05 , radius1 )
plt.title(Casual or registered in the total lease) 工作日 由于工作日和休息日的天数差别对工作日和非工作日租赁数量取了平均值对一周中每天的租赁数量求和
workingday_dfday_df.groupby([workingday], as_indexTrue).agg({casual:mean, registered:mean})
workingday_df_0 workingday_df.loc[0]
workingday_df_1 workingday_df.loc[1]# plt.axes(aspectequal)
fig plt.figure(figsize(8,6))
plt.subplots_adjust(hspace0.5, wspace0.2) #设置子图表间隔
grid plt.GridSpec(2, 2, wspace0.5, hspace0.5) #设置子图表坐标轴 对齐plt.subplot2grid((2,2),(1,0), rowspan2)
width 0.3 # 设置条宽p1 plt.bar(workingday_df.index,workingday_df[casual], width)
p2 plt.bar(workingday_df.index,workingday_df[registered], width,bottomworkingday_df[casual])
plt.title(Average number of rentals initiated per day)
plt.xticks([0,1], (nonworking day, working day),rotation20)
plt.legend((p1[0], p2[0]), (casual, registered))plt.subplot2grid((2,2),(0,0))
plt.pie(workingday_df_0, labels[casual,registered], autopct%1.1f%%, pctdistance0.6 , labeldistance1.35 , radius1.3)
plt.axis(equal)
plt.title(nonworking day)plt.subplot2grid((2,2),(0,1))
plt.pie(workingday_df_1, labels[casual,registered], autopct%1.1f%%, pctdistance0.6 , labeldistance1.35 , radius1.3)
plt.title(working day)
plt.axis(equal) weekday_df day_df.groupby([weekday], as_indexTrue).agg({casual:mean, registered:mean})
weekday_df.plot.bar(stackedTrue , title Average number of rentals initiated per day by weekday) 对比图可发现
工作日会员用户出行数量较多临时用户出行数量较少周末会员用户租赁数量降低临时用户租赁数量增加。
节假日 由于节假日在一年中数量占比非常少先来看一每年的节假日下有几天
holiday_counday_df.groupby(year, as_indexTrue).agg({holiday:sum})
holiday_coun 假期的天数占一年天数的份额十分少所以对假期和非假期取日平均值
holiday_df day_df.groupby(holiday, as_indexTrue).agg({casual:mean, registered:mean})
holiday_df.plot.bar(stackedTrue , title Average number of rentals initiated per day by holiday or not) 节假日会员或非会员使用量都比非节假日多符合规律。
3.3、预测性分析
3.3.1、选择特征值
根据前面的观察决定将时段hour、温度temp、湿度humidity、年份year、月份month、季节season、天气等级weather、风速windspeed_rfr、星期几weekday、是否工作日workingday、是否假日holiday11项作为特征值。由于CART决策树使用二分类所以将多类别型数据使用one-hot转化成多个二分型类别
dummies_month pd.get_dummies(Bike_data[month], prefix month)
dummies_seasonpd.get_dummies(Bike_data[season],prefixseason)
dummies_weatherpd.get_dummies(Bike_data[weather],prefixweather)
dummies_yearpd.get_dummies(Bike_data[year],prefixyear)
#把5个新的DF和原来的表连接起来
Bike_datapd.concat([Bike_data,dummies_month,dummies_season,dummies_weather,dummies_year],axis1)
3.3.2、训练集、测试集分离
dataTrain Bike_data[pd.notnull(Bike_data[count])]
dataTest Bike_data[~pd.notnull(Bike_data[count])].sort_values(by[datetime])
datetimecol dataTest[datetime]
yLabelsdataTrain[count]
yLabels_lognp.log(yLabels)
3.3.3、多余特征值舍弃 dropFeatures [casual , count , datetime , date , registered ,windspeed , atemp , month,season,weather, year ]dataTrain dataTrain.drop(dropFeatures , axis1)
dataTest dataTest.drop(dropFeatures , axis1)
3.3.4、选择模型、训练模型
rfModel RandomForestRegressor(n_estimators1000 , random_state 42)rfModel.fit(dataTrain , yLabels_log)preds rfModel.predict( X dataTrain)
3.3.5、预测测试集数据
predsTest rfModel.predict(X dataTest)submissionpd.DataFrame({datetime:datetimecol , count:[max(0,x) for x in np.exp(predsTest)]})submission.to_csv(rD:\A\Data\ufo\/bike_predictions.csv,indexFalse)