這一關(guān)屬于進(jìn)階關(guān)脂男,難度相比前面提高了不少宰翅,所以花費(fèi)的時(shí)間也多了一些。
本關(guān)的學(xué)習(xí)內(nèi)容主要為:如何編寫(xiě)函數(shù);數(shù)據(jù)處理:dplyr, ggplot2耸彪;如何編寫(xiě)業(yè)務(wù)模塊蝉娜;代碼如何調(diào)試。
1.如何編寫(xiě)函數(shù)
1.1 自編函數(shù)模板
my_fun <- function(arg1,arg2,...){
body
ruturn(data)
}
例如下面荧呐,若add(1,2)概疆,結(jié)果z=3
add <- function(x,y) {
z <- x+y
return(z)
}
1.2 控制語(yǔ)句-循環(huán)和條件
1.2.1 for 循環(huán)的基本模板
for(i in data){
body
}
假設(shè)有一項(xiàng)重復(fù)性工作,如下:
library(stringr)
print(str_c("第幾次吃飯",1,sep=":"))
print(str_c("第幾次吃飯",2,sep=":"))
print(str_c("第幾次吃飯",3,sep=":"))
重復(fù)去寫(xiě)1,2,3,...會(huì)很麻煩楣颠,我們可以用for循環(huán)來(lái)簡(jiǎn)化:
for(i in 1:3) {
print(
str_c("第幾次吃飯",i,sep=":")
)
}
1.2.2 while循環(huán)的基本模板
while (condition){
body
}
例如:
i <- 10
while(i>0){
print(
i <- i-1)
}
注意:while 一定要有循環(huán)結(jié)束的判斷條件,否則會(huì)無(wú)限循環(huán)下去。
1.2.3 條件語(yǔ)句的基本模板
if(condition){
body
}else{
body
}
例如錢(qián)包內(nèi)有100侧馅,吃飯花費(fèi)30,余額提醒:
money <- 100
if(money>0){
money <- money-30
print("錢(qián)包還有錢(qián),不需要取錢(qián)")
}else{
print("錢(qián)包沒(méi)有錢(qián),去取款機(jī)吧")
}
再舉一個(gè)復(fù)雜點(diǎn)的例子:飯卡余額1000酬屉,每天吃3頓飯,每頓5元垛吗,余額低于5元蔚舀,提示:
everday <- function(eatNumber,money){
for(i in eatNumber){
eatNumber <- str_c("今天吃第幾次飯:",i,sep="")
money <- money-5*i
print(money)
print(eatNumber)
}
if(money<5){
print("飯卡沒(méi)錢(qián)了:去銀行取錢(qián)")
}else{
print("飯卡還有錢(qián):不用去銀行")
}
}
2.數(shù)據(jù)處理-dplyr、ggplot2
dplyr是一套數(shù)據(jù)處理工具礼患,它提供了多個(gè)函數(shù)來(lái)幫助你完成常見(jiàn)的數(shù)據(jù)處理工作:
- mutate()函數(shù)對(duì)已有列進(jìn)行數(shù)據(jù)運(yùn)算并添加為新列,類(lèi)似transform()
- select()根據(jù)列名選擇出需要的子集
- filter()基于數(shù)值挑選對(duì)象,可以按給定的邏輯條件篩選符合要求的子數(shù)據(jù)集
- summarise()對(duì)數(shù)據(jù)框調(diào)用函數(shù)進(jìn)行匯總操作, 返回一維的結(jié)果
- arrange()按給定的列名依次對(duì)行進(jìn)行排序领曼,默認(rèn)為升序,類(lèi)似order()
ggplot2是R中重要的繪圖工具: - ggplot2的核心理念是將繪圖與數(shù)據(jù)分離,數(shù)據(jù)相關(guān)的繪圖與數(shù)據(jù)無(wú)關(guān)的繪圖分離
- ggplot2是按圖層作圖
- ggplot2保有命令式作圖的調(diào)整函數(shù)幻碱,使其更具靈活性
- ggplot2將常見(jiàn)的統(tǒng)計(jì)變換融入到了繪圖中喇聊。
接下來(lái)誓篱,我們利用一個(gè)例子,來(lái)深入學(xué)習(xí)這兩個(gè)包。
2.1 數(shù)據(jù)分析流程
數(shù)據(jù)預(yù)分析步驟:理解數(shù)據(jù)-數(shù)據(jù)導(dǎo)入-數(shù)據(jù)預(yù)處理-數(shù)據(jù)計(jì)算-數(shù)據(jù)顯示赎线。
2.1.1 數(shù)據(jù)導(dǎo)入
首先加載包和數(shù)據(jù)集。
install.packages("dplyr")
install.packages("nycflights13")
library(dplyr)
library(nycflights13)
2.1.2 數(shù)據(jù)預(yù)處理步驟
進(jìn)行數(shù)據(jù)預(yù)處理的步驟:選擇子集-列重命名-刪除缺失數(shù)據(jù)-處理日期-類(lèi)型轉(zhuǎn)換-數(shù)據(jù)排序。
2.1.2.1 選擇子集
確定分析目標(biāo):航班航線(xiàn)距離與延誤時(shí)間的關(guān)系
# 查看數(shù)據(jù)結(jié)構(gòu)
str(flights)
myFlights <- select(flights,year,month,day,
dep_delay,arr_delay,distance,dest)
# select也可以進(jìn)行模糊匹配
select(data,
starts_with("abc"), #以abc開(kāi)頭
ends_with("xyz"), #以xyz結(jié)尾
contains("ijk"), #包含ijk
matches("(.)\\1")) #正則表達(dá)式,字符或數(shù)據(jù)匹配
2.1.2.2 列名重命名
myFlights <- rename(myFlights,destination=dest)
#tips:新列名在前竞惋,舊列名在后
2.1.2.3 刪除缺失數(shù)據(jù)
myFlights <- filter(myFlights,!is.na(dep_delay),!is.na(arr_delay))
filter()更多用法:
# 查找數(shù)據(jù)
filter(myFlights,month==12,day==25) #查找12.25的航班
filter(myFlights,arr_delay>120|dep_delay>120) #延誤超2h的航班
2.1.2.4 數(shù)據(jù)排序
這里我們用的是dplyr中的arrange()函數(shù)嗓奢,默認(rèn)為升序钳幅,desc()讓表示降序诬乞。
arrange(myFlights,dep_delay)
arrange(myFlights,desc(dep_delay))
2.1.3 數(shù)據(jù)計(jì)算
用dplyr包的分組函數(shù)group_by()和組合函數(shù)summarise()來(lái)進(jìn)行計(jì)算票堵。
數(shù)據(jù)處理的一般模式: Split(數(shù)據(jù)分組) - Apply(應(yīng)用函數(shù)) - Combine(組合結(jié)果)
# 按照目的地進(jìn)行分組
by_dest <- group_by(myFlights,destination)
# 求平均到達(dá)延誤時(shí)間和平均航行里程
delay <- summarise(by_dest,
count=n(), #航班數(shù)-每個(gè)分組有多少數(shù)據(jù)
dist=mean(distance,na.rm = TRUE),
delay=mean(arr_delay,na.rm=TRUE))
# 移除噪音數(shù)據(jù)--移除樣本數(shù)量較小的數(shù)據(jù)
delay <- filter(delay,count>20)
以上的過(guò)程,可以利用管道:%>% 進(jìn)行簡(jiǎn)化
delays <- flights%>%
group_by(dest)%>%
summarise(
count=n(),
dist=mean(distance,na.rm = TRUE),
delay=mean(arr_delay,na.rm = TRUE)
)%>%
filter(count>20)
2.1.4 數(shù)據(jù)顯示
數(shù)據(jù)顯示要用到繪圖包ggplot2瞳浦,ggplot()是一個(gè)圖層一個(gè)圖層來(lái)繪制圖形的担映,用其中的加號(hào)"+"來(lái)結(jié)合各個(gè)圖層,ggplot2繪圖的一般模板為:
# ggplot(data = <DATA> ) + #創(chuàng)建畫(huà)板
# <GEOM_FUNCTION>(mapping=aes( <MAPPINGS>)) #添加圖層
應(yīng)用到本實(shí)例中叫潦,ggplot()括號(hào)內(nèi)的參數(shù)是要使用的數(shù)據(jù)蝇完,然后是geom_point(mapping = aes(x = dist, y = delay)),這是用來(lái)繪制散點(diǎn)圖的矗蕊,x軸為距離dist短蜕,y軸為延遲時(shí)間delay。 geom_smooth(mapping = aes(x = dist, y = delay))用來(lái)給圖加入平滑的曲線(xiàn)傻咖,以展示x和y的關(guān)系朋魔。
ggplot(data=delay)+
geom_point(mapping = aes(x=dist,y=delay))+
geom_smooth(mapping = aes(x=dist,y=delay))
3.如何編寫(xiě)業(yè)務(wù)模塊
3.1 模塊介紹
一個(gè)項(xiàng)目通常會(huì)有以下幾個(gè)模塊:
- 視圖模塊(view):數(shù)據(jù)顯示的實(shí)現(xiàn)代碼
- 業(yè)務(wù)邏輯模塊(service):數(shù)據(jù)處理的代碼
- 數(shù)據(jù)層模塊(db):數(shù)據(jù)分析要連接的數(shù)據(jù)庫(kù)
各個(gè)模塊的文件會(huì)放在相同名字的文件夾里面,根據(jù)需要還可以創(chuàng)建其他模塊: - 公共模塊(util):放項(xiàng)目的公共材料卿操,比如項(xiàng)目的配置信息
- 公共數(shù)據(jù)(data):數(shù)據(jù)分析用到的數(shù)據(jù)
- 日志模塊(log):數(shù)據(jù)處理流程
- 數(shù)據(jù)輸出模塊(output):放數(shù)據(jù)分析的結(jié)果警检,比如繪制的圖形和Excel文件等
例如本例中,util里的packageManager.R代碼:
#管理安裝包
# 數(shù)據(jù)包
packages <- c("nycflights13")
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
#字符串包
packages <- c("stringr")
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
#圖形包
packages <- c("ggplot2")
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
#數(shù)據(jù)處理包
packages <- c("dplyr")
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
3.2 業(yè)務(wù)邏輯模塊
在業(yè)務(wù)邏輯模塊的文件夾(service)里創(chuàng)建R腳本flight.R:
install.packages("dplyr")
install.packages("nycflights13")
library(dplyr)
library(nycflights13)# for data
#航班航行距離與延誤時(shí)間的關(guān)系
#輸入:不需要輸入?yún)?shù)
#輸出:返回每個(gè)目的地的平均航行距離害淤,平均延誤時(shí)間
disDelay <- function(){
#選擇子集
myFlights <- select(flights,
year,month,day,
dep_delay,arr_delay,
distance,dest)
#列名重命名扇雕,等號(hào)左邊是新列名,右邊是就列名
myFlights <- rename(myFlights, destination = dest)
#刪除缺失數(shù)據(jù)窥摄,這里的空值NA代表航班取消
myFlights <- filter(myFlights,
!is.na(dep_delay),
!is.na(arr_delay))
#數(shù)據(jù)排序
myFlights <- arrange(myFlights, desc(dep_delay))
#數(shù)據(jù)計(jì)算:航班航行距離與延誤時(shí)間的關(guān)系
delay <- myFlights %>%
group_by(destination) %>%
summarise(
count = n(),
dist = mean(distance, na.rm = TRUE),
delay = mean(arr_delay, na.rm = TRUE)
) %>%
filter(count > 20)
return(delay)
}
3.3 視圖模塊
在視圖模塊文件夾(view)里把前面的數(shù)據(jù)顯示實(shí)現(xiàn)代碼(flightView.R)存入:
library(ggplot2)
library(stringr)
#獲取當(dāng)前項(xiàng)目運(yùn)行根路徑
projectPath <- getwd()
#獲取service路徑
servicePath <- str_c(projectPath,
"service",
"flight.R",
sep="/")
#編譯R文件镶奉,利用source()調(diào)用外部代碼并運(yùn)行
source(servicePath)
#業(yè)務(wù)邏輯:航班航行距離與延誤時(shí)間的關(guān)系
delay <- disDelay()
#繪制散點(diǎn)圖
view <- ggplot(data = delay) +
geom_point(mapping = aes(x = dist, y = delay)) +
geom_smooth(mapping = aes(x = dist, y = delay))
#定義散點(diǎn)圖保存路徑
outputpath <- str_c(projectPath,"output","delayFlight.jpg",sep="/")
#利用ggsave()來(lái)保存散點(diǎn)圖到上面的路徑中
ggsave(filename=outputpath, plot=view)
4.代碼如何調(diào)試
Rstudio中的代碼搜索功能,例如想知道業(yè)務(wù)邏輯模塊中的disDelay 具體代碼崭放,可以雙擊選中函數(shù)-進(jìn)入函數(shù)定義的地方:Rstudio-Code-Go to Function Definition哨苛。
一個(gè)簡(jiǎn)單的代碼調(diào)試過(guò)程:
代碼出現(xiàn)錯(cuò)誤-錯(cuò)誤在哪塊代碼-理解錯(cuò)誤代碼大概什么意思-打斷點(diǎn)(stop)-編譯(source)-重新執(zhí)行代碼-找到錯(cuò)誤原因。
寫(xiě)的比較簡(jiǎn)單币砂,大家可以找一些參考資料學(xué)習(xí)建峭。