kaggle小黃車競賽 得分:0.41038

在參與泰坦尼克競賽(zhuanlan.zhihu.com/p/27) 中得來的經驗,以及數據思維。也同樣可以用於小黃車的競賽中。n

首先先導入包

library(readr) nlibrary(plyr)nlibrary(stringr)n

其次導入數據

#setwd是設定路徑的意思nsetwd("C:/Users/wlh/Desktop/下載的數據")ntrain<-read.csv("train.csv")ntest<-read.csv("test.csv")n

觀測數據,發現測試數據比訓練數據少了三個觀測分別是註冊,臨時,計數。

怎麼辦呢?那就在測試數據里加上這哥仨吧

#在測試數據里加上缺失的三個值ntest$registered<-0ntest$casual<-0ntest$count<-0ndata<-rbind(train,test)n

用str()看看這裡面都包含什麼數據

str(data)n

結果如下

data.frame:t17379 obs. of 12 variables:n $ datetime : Factor w/ 17379 levels "2011-01-01 00:00:00",..: 1 2 3 4 5 6 7 8 9 10 ...n $ season : int 1 1 1 1 1 1 1 1 1 1 ...n $ holiday : int 0 0 0 0 0 0 0 0 0 0 ...n $ workingday: int 0 0 0 0 0 0 0 0 0 0 ...n $ weather : int 1 1 1 1 1 2 1 1 1 1 ...n $ temp : num 9.84 9.02 9.02 9.84 9.84 ...n $ atemp : num 14.4 13.6 13.6 14.4 14.4 ...n $ humidity : int 81 80 80 75 75 75 80 86 75 76 ...n $ windspeed : num 0 0 0 0 0 ...n $ casual : num 3 8 5 3 0 0 2 1 1 8 ...n $ registered: num 13 32 27 10 1 1 0 2 7 6 ...n $ count : num 16 40 32 13 1 1 2 3 8 14 ...n

可以看出共有觀測17379條,12條變數

日期時間(datetime):日期和時間以「mm-dd- yyyy hh:mm:ss」格式

季節(season):1為春,2為夏,3為秋,4為冬

假期(holiday):1/0

工作日(workingday):1/0

天氣(weather):四類天氣

1->清除,幾朵雲,部分多雲,部分多雲

2->迷霧+多雲,霧+破碎的雲霧,霧+少雲,霧

3->輕雪和雨+雷暴+分散的雲彩,小雨+分散的雲彩

4->大雨+冰托盤+雷雨+霧,雪+霧

溫度(temp):每小時攝氏溫度

??(atemp):像是一種加過權重之後的溫度,反正跟temp是強正相關

濕度(humidity):濕度

風速(windspeed):風速

casual :休閑用戶

registered:註冊用戶

count:共計數

ps:數據集顯示兩年(2011年和2012年)的數據。訓練數據集是每個月的前19天。測試數據集是從20日到次月。

找出缺失值

#找缺失值ntable(is.na(data))n

結果如下

FALSE n208548 n

其實木有缺失值

了解數值變數的分布,然後生成數值變數的頻率表。繪製每個數值變數的直方圖,並分析

#繪製每個觀測的直方圖並分析n#四行兩列npar(mfrow=c(4,2))n#寬度和長度npar(mar = rep(2, 4))nhist(data$season)nhist(data$weather)nhist(data$humidity)nhist(data$holiday)nhist(data$workingday)nhist(data$temp)nhist(data$atemp)nhist(data$windspeed)n

如圖:

通過觀察上圖可以看出一些影響

1.四季的影響不大

2.天氣的影響比較大,從好到不好,自行車的使用量越來越低

3.當假期為0,工作日為1時自行車的使用量就比較大

4.溫度太高或者太低了都會影響使用量

5.風速從5到20這個時候自行車使用量比較大,可以推測在這個風速里騎車是比價愉悅的

將離散型轉換為因子型的(季節,天氣,假期,工作日)

data$season=as.factor(data$season)ndata$weather=as.factor(data$weather)ndata$holiday=as.factor(data$holiday)ndata$workingday=as.factor(data$workingday)n

假設生成

現在你對數據已經有了一個大致的了解,下面讓我們來根據一些基本的經驗來對自行車的使用量進行假設

24小時趨勢:上下班高峰期使用量就很高。晚上10點到凌晨4點需求低

一周趨勢:平日用車比節假日高

有雨有雪:與晴天相比,下雨(雪)天的自行車需求將會下降。同樣,較高的濕度會降低需求,反之亦然。

溫度:溫度適宜的情況下使用量必加大

註冊用戶與時間:由於註冊用戶數量隨著時間的推移得增多,總需求應該趨向於升高

假設檢驗

下面來逐一分析上面的假設檢驗

每日趨勢:

data$hour=substr(data$datetime,12,13)ndata$hour=as.factor(data$hour)n

畫圖,判斷假設是否正確

#把訓練的前20天和測試的後10天左右提出來ntrain=data[as.integer(substr(data$datetime,9,10))<20,]ntest=data[as.integer(substr(data$datetime,9,10))>19,]n#畫圖nboxplot(train$count~train$hour,xlab="hour", ylab="count of users")n

如圖:

可以看出和我們的假設差不多

上下班時間是用車高峰,而低峰期是在晚上10點到次日凌晨6點。其他時間為平均用車量

然後我們再來看一下註冊用戶和臨時用戶的差別:

#臨時用戶nboxplot(train$casual~train$hour,xlab="hour", ylab="count of users")n

如圖:

可以看出臨時用戶傾向於在白天的時候隨便用用,基本上都是平均值

#註冊用戶nboxplot(train$registered~train$hour,xlab="hour", ylab="count of users")n

如圖:

註冊用戶更傾向於上下班高峰期用

但是你會發現,這倆圖有好些個異常值,應該不是由錯誤導致的。他們可能是同一群人騎自行車但是未註冊的結果,為了處理這些離群值,我們將使用對數變換。

boxplot(log(train$count)~train$hour,xlab="hour",ylab="log(count)")n

如圖:

一周趨勢:

#把date$datetime的年月日拆出來ndate<-substr(data$datetime,1,10)n#拆出來之後轉換成星期ndays<-weekdays(as.Date(date))ndata$day<-daysn

註冊用戶畫圖:

臨時用戶:

#畫臨時用戶的圖nboxplot(train$casual~train$day,xlab="day", ylab="users")n

如圖:

可以看出星期六星期天的用戶是增加的

雨(雪)的影響:在變數中雖然沒有專門的雨量數據,但是在天氣(weather)這裡面有響應的因素,3里有小雨(雪),4里有大雨(雪)

#畫圖,天氣和註冊用戶的關係nboxplot(train$registered~train$weather,xlab="weather", ylab="registered users")n

如圖:

#畫圖,天氣和休閑用戶的關係nboxplot(train$casual~train$weather,xlab="weather", ylab="casual users")n

如圖:

從圖中可以看出非常符合我們的預期

溫度,風速和濕度:這些不是離散型的,是連續的。所以我們用相關來驗證假設

#溫度,風速和濕度的相關關係nsub<-data.frame(train$registered,train$casual,train$count,train$temp,train$humidity,train$atemp,train$windspeed)nsubT<-cor(sub)n

如下表:

從表中可以看出,溫度和註冊,休閑,總計這三個變數差不多都是正相關關係,而濕度和風速跟這三兄弟的關係就不是很大了。溫度和atemp是高度相關。

時間:看看時間對於用戶數的影響

#隨著時間的推移,用戶數的變化ndata$year=substr(data$datetime,1,4)ndata$year=as.factor(data$year)ntrain=data[as.integer(substr(data$datetime,9,10))<20,]ntest=data[as.integer(substr(data$datetime,9,10))>19,]nboxplot(train$count~train$year,xlab="年", ylab="用戶總量")n

如圖:

結論是用戶數增加。

決策樹

讓我們用決策樹來增加模型的預測能力

第一步添加決策樹相應的包

#決策樹要用到的包nlibrary(rpart)#在我的泰坦尼克競賽里有對這個包的介紹nlibrary(rattle) #這些庫將用於為決策樹模型提供良好的可視化繪圖nlibrary(rpart.plot)#繪製「rpart」模型:「plot.rpart」的增強版本nlibrary(RColorBrewer)#配色方案n

然後話關於小時的決策樹的圖

#訓練數據轉換類型ntrain$hour=as.integer(train$hour)n#測試數據轉換類型ntest$hour=as.integer(test$hour)n#用小時生成決策樹nd=rpart(registered~hour,data=train)n#畫圖nfancyRpartPlot(d)n

如圖:

查看節點,手動添加倉位(註冊用戶)

data=rbind(train,test)ndata$dp_reg=0ndata$dp_reg[data$hour<8]=1ndata$dp_reg[data$hour>=22]=2ndata$dp_reg[data$hour>9 & data$hour<18]=3ndata$dp_reg[data$hour==8]=4ndata$dp_reg[data$hour==9]=5ndata$dp_reg[data$hour==20 | data$hour==21]=6ndata$dp_reg[data$hour==19 | data$hour==18]=7n

添加倉位(休閑用戶)

#休閑用戶nb=rpart(casual~hour,data=train)nfancyRpartPlot(b)n

如圖:

#手動添加ndata$dp_cas=0ndata$dp_cas[data$hour==9]=1ndata$dp_cas[data$hour<=8]=2ndata$dp_cas[data$hour>=10&data$hour<=19]=3ndata$dp_cas[data$hour>=20]=4n

溫度同上:

#溫度(註冊)nt=rpart(registered~temp,data=train)nfancyRpartPlot(t)n

如圖:

#添加註冊ndata$temp_reg=0ndata$temp_reg[data$temp<13]=1ndata$temp_reg[data$temp>=13&data$temp<23]=2ndata$temp_reg[data$temp>=23&data$temp<30]=3ndata$temp_reg[data$temp>=30]=4n

溫度(休閑)

#溫度(休閑)nt1=rpart(casual~temp,data=train)nfancyRpartPlot(t1)n

如圖:

#添加休閑ndata$temp_cas=0ndata$temp_cas[data$temp<15]=1ndata$temp_cas[data$temp>=15&data$temp<23]=2ndata$temp_cas[data$temp>=23&data$temp<30]=3ndata$temp_cas[data$temp>=30]=4n

添加年份:在這裡先把月份提取出來,然後按照每個季度一個倉位,建8個倉位

#提取月份ndata$month=substr(data$datetime,6,7)ndata$month=as.factor(data$month)ntrain=data[as.integer(substr(data$datetime,9,10))<20,]ntest=data[as.integer(substr(data$datetime,9,10))>19,]n#轉換類型ndata$month=as.integer(data$month)n

#手動添加ndata$year_part[data$year==2011]=1ndata$year_part[data$year==2011 & data$month>3]=2ndata$year_part[data$year==2011 & data$month>6]=3ndata$year_part[data$year==2011 & data$month>9]=4ndata$year_part[data$year==2012]=5ndata$year_part[data$year==2012 & data$month>3]=6ndata$year_part[data$year==2012 & data$month>6]=7ndata$year_part[data$year==2012 & data$month>9]=8ntable(data$year_part)n

日期:創建一個變數,有「平日」、「周末」和「假日」

data$day_type=""ndata$day_type[data$holiday==0 & data$workingday==0]="weekend"ndata$day_type[data$holiday==1]="holiday"ndata$day_type[data$holiday==0 & data$workingday==1]="working day"n

周末:為周末創建一個獨立的變數

data$weekend=0ndata$weekend[data$day=="Sunday" | data$day=="Saturday" ]=1n

開始建模

首先把character的數據類型都轉換成factor,否則隨機森林不支持

#轉換數據類型,否則隨機森林不支持ndata$day=as.factor(data$day)ndata$day_type=as.factor(data$day_type)n

我們之前分析過由於註冊,休閑,計數。這哥仨有很多自然離群值,所以這裡就把他們都轉換成對數。

#取對數ndata$logreg<-log(data$registered+1)ndata$logcas<-log(data$casual+1)n

加一是為了處理註冊和休閑這倆觀測的0值

#將data里的所有觀測和類型統統賦值給train,testntrain=data[as.integer(substr(data$datetime,9,10))<20,]ntest=data[as.integer(substr(data$datetime,9,10))>19,]n

預測

#預測註冊用戶的對數nset.seed(415)nfit1 <- randomForest(logreg ~ hour +workingday+day+holiday+ day_type +temp_reg+humidity+atemp+windspeed+season+weather+dp_reg+weekend+year+year_part, data=train,importance=TRUE, ntree=250)npred1=predict(fit1,test)ntest$logreg=pred1n

可能我的電腦比較渣,這裡運算了1個小時

#預測休閑用戶的對數nset.seed(415)nfit2 <- randomForest(logcas ~hour + day_type+day+humidity+atemp+temp_cas+windspeed+season+weather+holiday+workingday+dp_cas+weekend+year+year_part, data=train,importance=TRUE, ntree=250)npred2=predict(fit2,test)ntest$logcas=pred2n

啊,又小一個小時過去了。。。

寫入文件上傳

#重新轉換預測變數,然後將count的輸出寫入文件ntest$registered=exp(test$logreg)-1ntest$casual=exp(test$logcas)-1ntest$count=test$casual+test$registeredns<-data.frame(datetime=test$datetime,count=test$count)nwrite.csv(s,file="pre3.csv",row.names=FALSE)n

由於沒有排名系統所以只有得分......

得了0.41038分


推薦閱讀:

Kaggle—So Easy!百行代碼實現排名Top 5%的圖像分類比賽
Zillow簡介(二)如何重構經紀行業的產業鏈?
用Python下載Kaggle數據
Titanic: kaggle入門實踐-top10%(附Python代碼)
Zillow Prize競賽系列--(一)競賽簡介

TAG:数据分析 | R编程语言 | Kaggle |