# **R 學習筆記** 在R中,字母大小寫是有差別的。 若要中斷程式,按"esc"。 ## Basic ### 基本處理語法 | 符號 | 代表指令 | | -------- | -------- | | # | 註解 | | <- , = | 指定 | | == | 等於 | | ! | not | | & | and | | l | or | | ? | 文件說明 | |%in% |是否介於該範圍內| ### Package相關指定 ``` R #呼叫套件 library(package) #檢視指定套件,若無安裝,則無反應 require(package) #同上,若無安裝,則會進行安裝 ``` * 若要安裝套件,有兩種方式 ``` R install.packages("name") #直接安裝套件 install.packages("name", repos="web-site") #透過網頁載入套件 ``` 套件相關指令 ```R update.package() #更新套件,若無指定套件,則更新所有套件 help(package="name") / ?name #套件說明 help.search("name") help.start() #顯示網路相關說明 search() #顯示所有下載套件 searchpaths() #顯示載入套件的路徑 example() #執行函數的範例 ``` * 基本函數指令 ```R #指定資料檔,之後可直接輸入欄位名稱 attach(data) / with(data,{可選取欄位或條件}) assign("a",1) #新增變數 getwd() #顯示目前指定路徑 dir() #顯示目前路徑底下的資料夾 setwd("path") #設定資料夾路徑 apropos("n") #尋找函數,可輸入部分名稱 scan() #讀取或輸入資料 objects() / is() #顯示所有物件 attributes() / attr() #顯示檔案屬性 rm() #移除物件 sink() #輸出結果 nrow(a) #計算列數 ncol(a) #計算行數 dim(a) #計算行、列數 nchar(a) #計算字元個數 length(a) #計算list長度 head(name,n=2L) #檢視前幾筆資料內容 tail(name,n=nL) #檢視後幾筆資料內容 rename(data,new_name=old_name) #重新命名 paste(a,b,c) #合併字串 unique(a) #去重複值 diff(a) #相減(後-前) scale(a) #標準化 identical(a,b) #判斷兩a,b內容是否一樣 ``` ### 基本運算 1. 資料屬性 | Integer | Double | Numeric | Character| Logical | | -------- | -------- | -------- | -------- | -------- | | 整數 | 小數 |實數 | 文字 | 邏輯 | 2. 運算子 | + | - | * | / | ^, ** | sqrt() | %/% | %% | | -- | -- | -- |-- | -- | -- |-- | -- | | 加 | 減 | 乘 | 除 | 次方 | 開根號 |商數 | 餘數 | 3. 相關運算函數 ```R= #判斷資料屬性 class() is.numeric() #判斷是否為此屬性 is.integer() is.character() as.numeric() #指定資料屬性 as.integer() as.character() sign #判斷正/負數 abs() log() / log2() / log10() exp() sum() / cumsum() #加總 / 累積加總 prod() / cumprod() #相乘 / 累積相乘 mean() round(a,digits=n) #四捨五入 ``` | | Character | Numeric | Integer |Complex | Logical | | -- | -- | -- |-- | -- | -- | | as.integer | X | O | O | O | O | | is.integer | F | F | T | F | F | 4. %>%運算子 其屬於`magrittr`套件中的運算子,導入一種管線(pipe)的概念, 讀取程式碼的方式從左到右,讓程式碼更簡潔、語意更清楚。 ```R library(magrittr) x <- 1:10 >#一般寫法 mean(x) >#運用%>%運算子 x %>% mean ``` ## 變數結構 ### 向量 Vector 以```c()```表示, 其元素只會顯示一種資料型態, 每個型態強弱不同: char > complex > numeric > integer > logical * 以指標/名稱檢視資料 ```r= #example x <- c(a=1, b=2, c=3 ) #列出所有資訊 > x[1] a 1 #列出元素值 > x[[1]] [1] 1 #列出元素資訊 > x["a"] a 1 #列出元素值 > x[["a"]] [1] 1 > x[1:2] a b 1 2 ``` 相關函數指令 ```R seq(from= , to= , by=) #產生序列,by可設定等差級距 rep(x, time= , each=) #產生重複值,each每組重複次數 sort() #排序 rank() #各向量元素的排序值 ``` ### 陣列 Array 所有陣列的元素屬性必須一致。 兩種定義方式, ```R rbind(x,y) #合併row(橫) cbind(x,y) #合併column(直) array(x,c(a,b,c)) #多維度的向量 ``` 相關函數指令 ```R dim() #列出維度資訊 ncol() #計算column個數 nrow() #計算row個數 aperm() #將陣列轉置 ``` ### 矩陣 Matrix 二維陣列亦為矩陣,也可用```matrix()``` 相關函數指令 ```R t() #將矩陣轉置 %*% #矩陣相乘 diag() #產生對角矩陣 / 回傳矩陣對角向量 det() #計算矩陣行列式值,一定要對稱的情況 slove() #傳回矩證的反舉證 eigen() #計算矩陣的特徵向量與特徵值 rownames() #修改 / 查詢row 名稱 colnames() ``` ### 因子 Factor 因子像分級過後的向量 ```R #example x <-c(1,2,3,4,3,1) factor(x) [1] 1 2 3 4 3 1 Levels: 1 2 3 4 ``` 相關函數指令 ```R is.factor() #是否為因子 as.factor() #變數轉換為因子 is.ordered() #是否為排序過的因子 as.ordered() #變數轉換為排序的因子 which() #找出符合條件的指標 ``` ### 列表 List 可儲存不同型態的變數 相關函數 ```R as.list() #建立列表 is.list() #是否為列表 attributes() #查看所有元素名稱 ``` ### 資料框架 Data frame ```data.frame```中包含著column, row 每行都是相同長度的vector組成,資料型態都要一致 在宣告的過程中,盡量先定義好欄位名稱 ```R a <- 1:5 b <- c(a,b,c,d,e) ab <- data.frame(a,b) #表示顯示ab框架中的a欄位 ab$a ``` ### 字元資料 ```R #可使用兩種表示方法 x <- "data" x1 <- factor("data") #計算字串長度,但不適用於factor上 nchar(x) ``` ### 遺漏值 通常以```NA```跟```NULL```來表示 但```NULL```為不存在,非完成代表遺漏值,不能暫存於在`vector` ### 日期 在R中,是以1970年1月1日開始計算天數 與SAS不同(1960年1月1日)。 使用```lubridate, chron```套件可更輕易處裡日期及時間物件 ```R #天數 date <- as.Date("2012-06-06") #秒數 date <- as.POSIXct("2012-06-06 17:22") ``` ## 讀取資料 ### 1.讀取CSV 最好的使用方法是`read.table`函數,也可使用`read.csv`(也是從`read.table`延伸出來) ```R #example theUrl <- "http://www.jaredlander.com/data/TomatoFirst.csv" tomato <- read.table(file=theUrl,header=TRUE,sep=",") #sep為分隔符號,\t = tab分隔,; = 分號 ``` 這邊要注意的是,`data.frame`預設內容以`factor`型態儲存, 可在定義時設定`stringsAsFactors = FALSE`, 來預防文字屬性變成factor屬性。 ※若檔案內容有缺漏的部分,建議使用`read.csv2 / read.delim2`讀取資料 當資料量較大,則可考慮使用`readr`套件中的`read_delim`或`data.table`套件中的`fread`,會加快執行速度。(且這兩個函數也包含了`stringsAsFactors = FALSE`) * read_delim 主要用來讀取分隔符號的文件, 此預設第一行為欄位名稱。 ```R library(readr) theUrl <- "http://www.jaredlander.com/data/TomatoFirst.csv" tomato <- read_delim(file=theUrl,delim=',') ``` ![](https://i.imgur.com/XxquBs8.png) * fread ```R library(data.table) toma3 <- fread(input=theUrl, sep=',', header=TRUE) head(toma3) ``` ![](https://i.imgur.com/fbLAXAB.png) ### 2.讀取Excel 使用`readxl`中的`read_excel`函數 ```R #先確認要使用的分頁,再建立檔案 excel_sheets('C:/Users/Biostatistics/Downloads/ExcelExample.xlsx') win2 <- read_excel('C:/Users/Biostatistics/Downloads/ExcelExample.xlsx',sheet='Wine') ``` ### 3.讀取資料庫資料 大多資料庫是透過ODBC連結,其他無特定的資料庫可使用通用套件(RODBS) 要先使用dvDriver指定驅動程式(SQLite/ODBC),接著用dbConnect建立與資料庫連結, 在使用DBI套件再做其他分析。 ### 4.從網路提取資料 #### 4-1簡易HTML表格 可使用XML套件中的`readHTMLTable`來讀取 ```R install.packages("XML") library(rvest,XML) theURL <- "http://www........html" bowl <- readHTMLTable(theURL, which = 1, header = FALSE, stringsAsFactors = FALSE) ``` #### 4-2過濾網頁資料 使用Hadley Wickham的rvest套件將網頁資料轉換成可用的格式。 使用`read_html`可讀取網頁,建立存有html的xml_document物件。 以`%>%`來提取內容。 △在HTML中,定義類別需要使用句點` "."`,定義ID使用井字號` "#"` ```R library(xml2,rvest) rib <- read_html("https://www.jaredlander.com/data/ribalta.html") class(rib) rib ``` ![](https://i.imgur.com/dXwgqsF.png) #### 4-3讀取json資料 JSON(JavaScript Object Notation)是普遍的格式, 其將資料儲存為純文字檔的資料格式, 最主要使用兩個套件`rjson、jsonlite`。 ```R library(jsonlite) pizza <- fromJSON("https://www.jaredlander.com/data/PizzaFavorites.json") pizza ``` ## 基本繪圖功能 較常使用`ggplot2`套件來繪圖。 亦可使用`lattice`套件。 ### 1-1基本直方圖 ```R >hist(diamonds$carat, main="Carat Histogram", xlab="Carat") ``` ![](https://i.imgur.com/gRA1lwA.png) ### 1-2散佈圖 以formula形式,y ~ x 兩種方式都可以繪圖。 ```R >plot(price ~ carat, data=diamonds) >plot(diamonds$carat, diamonds$price) ``` ![](https://i.imgur.com/yB0NRy4.png) ### 1-3箱型圖 ```R >boxplot(diamonds$carat) ``` ![](https://i.imgur.com/bjNqZky.png) ### 1-4 ggplot2套件 由ggplot延伸。 1-4-1 ggplot2直方圖與機率密度圖 直方圖 ```R ggplot(data = diamonds) + geom_histogram(aes(x = carat)) ``` ![](https://i.imgur.com/Sxv3aRZ.png) 機率密度圖 ```R ggplot(data = diamonds) + geom_density(aes(x = carat), fill = 'grey50') ``` ![](https://i.imgur.com/EWFrXxC.png) 1-4-2 ggplot2散佈圖 ```R >ggplot(diamonds, aes(x = carat, y = price)) + geom_point() >#以顏色來區分類別 >g <- ggplot(diamonds, aes(x = carat, y = price)) >g + geom_point(aes(color = color)) ``` ![](https://i.imgur.com/ZA7zhvF.png) ![](https://i.imgur.com/ts5KvpW.png) 也可以繪製成多圖層,則需使用`facet_wrap `/ `facet_grid`函數。 ```R g + geom_point(aes(color = color)) + facet_wrap(~color) g + geom_point(aes(color = color)) + facet_grid(cut ~clarity) >#直方圖也可以成多圖層 ggplot(diamonds, aes(x = carat)) + geom_histogram() + facet_wrap(~color) ``` ![](https://i.imgur.com/MpEccAf.png) ![](https://i.imgur.com/WrCNyow.png) ![](https://i.imgur.com/g0MmWag.png) 1-4-3 ggplot2箱型圖和小提琴圖 ```R ggplot(diamonds, aes(y = carat, x = 1)) + geom_boxplot() ggplot(diamonds, aes(y = carat, x = cut)) + geom_boxplot() ``` ![](https://i.imgur.com/bv5Aeet.png) 只要轉換函數,即可將箱型圖轉換成小提琴圖 ```R ggplot(diamonds, aes(y = carat, x = cut)) + geom_violin() ``` ![](https://i.imgur.com/7086LPs.png) 1-4-4 ggplot2線形圖 ```R ggplot(economics, aes(x = date, y = pop)) + geom_line() ``` ![](https://i.imgur.com/tbN2l38.png) 另外一個案例 ```R >library(base,lubridate) >#建立年份和月份變數 >economics$year <- year(economics$date) >#label = true則表示顯示月份名稱,而非數字 >economics$month <- month(economics$date, label = TRUE) >econ2000 <- economics[which(economics$year >= 2000),] >library(scales) >#建立底圖 >g <- ggplot(econ2000, aes(x = month, y = pop)) >#用group來分群 >g <- g + geom_line(aes(color = factor(year), group=year)) >#格式化y軸 >g <- g + scale_color_discrete(name="year") >g <- g + scale_y_continuous(labels=comma) >g <- g + labs(title = 'Population Growth', x = "Month", y = "Population") >g ``` ![](https://i.imgur.com/gwQ4xk5.png) 1-4-5 主題樣式 `ggthemes`有內建很多常用的主題樣式,以下用例子呈現。 ```R >library(ggthemes) >g2 <- ggplot(diamonds, aes(x=carat,y=price)) + geom_point(aes(color=color)) >#分成四種繪圖風格呈現 >g2 + theme_economist() + scale_colour_economist() >g2 + theme_excel() + scale_colour_excel() >g2 + theme_tufte() >g2 + theme_wsj() ``` ![](https://i.imgur.com/dHMpK7P.png) ![](https://i.imgur.com/gW2HjJY.png) ![](https://i.imgur.com/Q3UeY3b.png) ![](https://i.imgur.com/BGEtWOS.png) ## R函數 最簡易的例子,建立"Hello, World!"的函數 ```R >say.hello <- function(){ print("Hello, World!") } ``` * 函數的引數 會使用`sprintf`函數,類似SAS中macro的概念。 ```R >sprintf("Hello %s", "Jared") ``` ![](https://i.imgur.com/AMS6nV2.png) 建立字串,以輸入引數的方式呈現 ```R hello.person <- function(name){ print(sprintf("Hello %s", name)) } hello.person('Jared') ``` ![](https://i.imgur.com/BCmhRch.png) * 預設引數值 預設值可以是任何有效物件,例如NULL、字元、數值等。 ```R hello.person2 <- function(first, last="Doe"){ print(sprintf("Hello %s %s", first, last)) } hello.person2("Jared") hello.person2("Jared","Lander") ``` ![](https://i.imgur.com/wuixNyk.png) * 附加引數 若無加上`"..."`,則會無法附加。 ```R hello.person2("Jared", extra="Goodbye") hello.person3 <- function(first, last="Doe",...){ print(sprintf("Hello %s %s", first, last)) } hello.person3("Jared", extra="Goodbye") ``` ![](https://i.imgur.com/aFjYrSN.png) * 回傳的值 除了函數主體最後一個值會被輸出,也可以用`return`的方式回傳數值 例子中輸出的結果都是一樣的。 ※`return`函數之後的指定不會被執行,因為函數已經被退出了。 ```R #一般函數執行 double.num <- function(x){ x*2 } double.num(5) #使用return函數 double.num2 <- function(x){ return(x*2) } double.num2(5) ``` * do.call 此函數允許使用者用`character`或者一個物件來指定函數名稱,所輸入的引數須以列表呈現。 ```R do.call("hello.person2",args= list(first="Jared",last="Lander")) #亦可這樣使用 run.this <- function(x, func=mean){ do.call(func,args = list(x)) } run.this(1:10) run.this(1:10,sum) ``` ## 流程控制 主要控制包括`If, else, ifelse, switch` ### If else基本架構 ```R check.bool <- function(x){ if(x == 1){ pirnt("hello") } else { print("goodbye") } } check.bool(1) ``` ### switch 如果要判斷的條件有很多個,則可使用`switch` ```R use.switch <- function(x){ switch(x, "a"="first", "b"="second", "z"="last", "c"="third", "other") } use.switch("g") ``` ### ifelse 此函數與Excel中if的用法較相似 ```R ifelse(1 == 1, "Yes", "No") [1] "Yes" toTest <- c(1, 1, 0, 1, 0, 1) ifelse(toTest == 1, "Yes", "No") [1] "Yes" "Yes" "No" "Yes" "No" "Yes" ``` ### 複合的條件檢測 若想要檢測多個物件則會使用邏輯運算子,亦即and(&, &&)和or(|, ||) 雙符號只單純比較單一個元素, 而雙符號最好用在`if`,而單符號最好用在`ifelse`。 ```R a <- c(1, 2, 0, 1) b <- c(2, 1, 0, 1) #可以觀察出單符號跟雙符號的差別 ifelse(a ==1 & b ==1, "Yes", "No") [1] "No" "No" "No" "Yes" ifelse(a ==1 && b ==1, "Yes", "No") [1] "No" ``` ## 迴圈 ### for迴圈 for需要的引數可分為三個部分, 變數、in、vector (變數在vector裡面) vector沒有限制,可以是數字或文字 ```R for(i in 1:10){ print(i) } ``` ### while迴圈 此迴圈較少使用 ```R x <- 1 while (x <= 5) { print(x) x <- x + 1 } ``` ### 迴圈的強制處理 通常會使用`next, break` ```R #此例為跳過3,其他都會print for (i in 1:10){ if (i ==3){ next } print(i) } #此例到4停止,print 1~3 for (i in 1:10){ if (i ==4){ break } print(i) } ``` ## 資料整理(data munging) 在資料分群做出一些重複性的操作,又稱為 "split-apply-combine"(拆開-套用-整合) ### Apply相關函數 `apply`函數限制性高,只能用於`matrix`,而且元素必須是同一型態。 `apply(X, MARGIN, FUN, ...)` 第一個為物件或data,第二個為=1對每一列、=2對每一行,要套用的函數 (sum, mean,...) ```R theMatrix <- matrix(1:9, nrow=3) apply(theMatrix, 1, sum) [1] 12 15 18 apply(theMatrix, 2, sum) [1] 6 15 24 ``` 假設矩陣中有NA值,使用sum則會變成NA,此時就要附加引數`"na.rm=TRUE"`, 就會跳過NA值繼續計算。 ```R apply(theMatrix, 1, sum) [1] 12 NA 18 apply(theMatrix, 1, sum, na.rm = TRUE) [1] 12 13 18 ``` ### lapply和sapply `lapply`是應用於`list、vector`,輸出也以`list`呈現, 而`sapply`應用於`list、vector`,輸出也以`vector`呈現。 ```R theList <- list(A = matrix(1:9,3),B=1:5, C=matrix(1:4,2),D=2) lapply(theList, sum) $A [1] 45 $B [1] 15 $C [1] 10 $D [1] 2 sapply(theList, sum) A B C D 45 15 10 2 ``` ### mapply 可以使用於多個`list`, 通常這種狀況大部分會使用迴圈,也可以使用此函數 ```R first <- list(A=matrix(1:16,4), B=matrix(1:15,5), c=1:5) second <- list(A=matrix(1:16,4), B=matrix(1:15,3), c=15:1) mapply(identical, first, second) A B c TRUE FALSE FALSE simpleFunc <- function(x,y){ NROW(x) + NROW(y) } mapply(simpleFunc, first, second) A B c 8 8 20 ``` ### aggregate 聚合資料 可以使用此函數來達成SQL中分群(group by)再聚合(aggregation)的概念 `aggregate(formula, data, FUN, ..., subset, na.action = na.omit)` formula為SQL group by的概念 FUN為要使用的函數 ```R >aggregate(price ~cut, diamonds, mean) cut price 1 Fair 4358.758 2 Good 3928.864 3 Very Good 3981.760 4 Premium 4584.258 5 Ideal 3457.542 ``` 但是aggregate執行速度較慢,還有其他像是`plyr, dplyr, data.table`是比較快的。 ### plyr套件 正好符合"拆開-套用-整合"的概念, 其函數主要由5個字母組成,都是ply結尾, 前兩個字母代表輸入和輸出資料的資料結構 舉幾個例子: | 函數 | 輸入資料 | 輸出資料 | | -------- | -------- | -------- | | ddply | data.frame |data.frame | | llply | list |list | | ldply | list |data.frame | | aaply | array/vector/matrix |array/vector/matrix | | d_ply | data.frame |無(用作邊際效應) | * ddply 需使用`data.frame`資料屬性, 以某些變數進行分群,做各種運算,再以`data.frame`形式回傳結果。 `with()`與SAS中data的概念很像。 ```R #.variables要針對哪個變項作分群,.fun要使用甚麼函數 careerOBP <- ddply(baseball, .variables = "id", .fun = obp) ``` * llply 以`list`的形式 ```R llply(theList,sum) laply(theList,sum) ``` * plyr輔助函數 例如`each()`可以套用多個function到函數中,但是不能使用自訂的function ```R aggregate(price ~cut, diamonds, each(mean, median)) ``` 另外一個蠻好用的函數為`idata.frame`,會更快速做資料,並節省記憶體。(與`data.frame`用法相同) ### data.table 此套件是對於`data.frame`功能的延伸和強化, ```R #data.frame與data.table的差別 theDF <- data.frame(a=1:10, b=letters[1:10], c=LETTERS[11:20], d=rep(c("One", "Two", "Three"), length.out=10)) theDT <- data.table(a=1:10, b=letters[1:10], c=LETTERS[11:20], d=rep(c("One", "Two", "Three"), length.out=10)) #可以注意到data.frame預設會把character轉換成factor > class(theDF$b) [1] "factor" > class(theDT$b) [1] "character" ``` 而在`data.table`中,若要單看某個欄位資料,要以`list`的方式指定 ```R theDT{, list(a, c)} ``` * 索引鍵(keys) ```R setkey(theDT,d) ``` * data.table資料分群計算 索引最主要的好處可以快速地進行資料分群計算, 雖然`aggregate`和`d*ply`函數都可做到,但`data.table`本身功能效率會比較快。 ```R >#example #aggregate與data.table的差別 aggregate(price ~cut,diamonds,mean) diamondsDT[, mean(price), by=cut] diamondsDT[, list(price=mean(price)),by= cut] ``` ## 使用dplyr 其用法與SQL相似 * pipe管線運算 (前面已有介紹過) * tbl物件 其最特別的是,在檢視時預設只有一部分會顯示出來。 tbl起源於`dplyr`,後續發展成`tibble`套件,其class仍然是tbl * select 1.可以採用巢狀的寫法,或使用pipe進行傳送 ```R select(diamonds, carat, price) diamonds %>% select(carat, price) diamonds %>% select(c(carat, price)) ``` 2.若要搜尋部分匹配(partial match),則可使用`dplyr`中的 `starts_with, ends_with, contains` (開頭 、 結尾 、 包含) ```R #會顯示開頭是c的變項 diamonds %>% select(starts_with("c")) ``` 3.可利用`matches`進行正規表示法搜尋 ```R #搜尋含有r, t的變項 diamonds %>% select(matches('r.+t')) ``` * filter 可透過`filter`篩選 ```R diamonds %>% filter(cut == 'Ideal') #可以透過%in%來篩選多個變項 diamonds %>% filter(cut %in% c('Ideal', 'Good')) ``` 若篩選條件會使用到某個變數的值,則需使用`filter_()` 當需要比較複雜的條件時,則建議使用`sprintf()`來組合運算式 ```R diamonds %>% filter_(sprintf("%s == '%s'", theCol, theCut)) ``` * slice 以選取特定的橫列,其需以`vector`的型態 ```R diamonds %>% slice(1:5) ``` * mutate 以新增或修改直行 ```R >diamonds %>% mutate(price/carat) ``` 若要儲存篩選運算結果,則可使用`magrittr`套件中的%<>%(pipe) ```R #此時%<>% 與 <- 意義相同 diamonds2 %<>% select(carat, price) %>% mutate(Ratio= price/carat, Double=Ratio*2) diamonds2 <- select(carat, price) %>% mutate(Ratio= price/carat, Double=Ratio*2) ``` * summarize 可直接使用於`data.frame`中,類似`with`函數 只會回傳單一數據結果 ```R summarize(diamonds, mean(price)) # A tibble: 1 x 1 `mean(price)` <dbl> 1 3933. ``` * group_by 將資料分群,與SQL概念相似 此作法會比`aggregate`更快速 ```R >diamonds %>% group_by(cut) %>% summarize(AvgPrice= mean(price)) ``` * arrange 用來排序,比`order, sort`函數更容易理解 * do 用於一般性的運算上,可任意套用函數 * dplyr用於資料庫 ```R download.file("http://www.jaredlander.com/data/diamonds.db", destfile="C:/Users/Biostatistics/Desktop/Udemy_R_lesson/diamonds.db",mode='wb') diaDBSource <- src_sqlite("C:/Users/Biostatistics/Desktop/Udemy_R_lesson/diamonds.db") install.packages("dbplyr") diaDBSource2 <- DBI::dbConnect(RSQLite::SQLite(), "C:/Users/Biostatistics/Desktop/Udemy_R_lesson/diamonds.db") diaDBSource diaDBSource2 diaTab <- tbl(diaDBSource, "diamonds") diaTab ``` ## purrr迭代 主要用於`list`型態,也可用於`vector` ### map 此套件中,最基礎的函數,可獨立套用於`list`每個元素中。 ```R #兩者是一樣的概念 >lapply(theList,sum) >theList %>% map(sum) ``` ### 指定map回傳的資料類型 | 函數 | 輸出型態 | | -------- | -------- | | map | list | | map_int | integer | | map_dbl | numeric | | map_chr | character | | map_lgl | logical | | map_df | data.frame | ```R theList %>% map_chr(class) ``` ## 資料整理 ### cbind, rbind資料合併 前面有介紹到,`data.frame`可透過`vector`使用`cbind, rbind`來結合 ### 資料連結 最常使用的函數為`merge`,` plyr`套件中的`join`和`data.table`的合併功能 * merge by是用來指定索引鍵,但此函數速度較慢 ```R aid90s00s <- merge(x=Aid_90s, y=Aid_00s, by.x=c("Country.Name","Program.Name"), by.y=c("Country.Name","Program.Name")) ``` * plyr join合併data.frame 此執行速度較快,但所連結的每個列表中,索引鍵的名稱必須是一樣的 可以指定左連結、右連結、內部或外部連結 ```R aid90s00sjoin <- join(x=Aid_90s, y=Aid_00s, by=c("Country.Name","Program.Name")) ``` * data.table合併 ```R #要先轉換成data.table,再進行合併,此例子為左連結 dt90 <- data.table(Aid_90s, key= c("Country.Name","Program.Name")) dt00 <- data.table(Aid_00s, key= c("Country.Name","Program.Name")) dt0090 <- dt90[dt00] ``` ### 用reshape2套件轉置 直行轉成橫列稱為melting data,橫列轉成直行稱為casting data * melt ```R #id.var為保留的欄位,variable.name轉置後的欄位名稱,value.name轉置後數值的欄位名稱 melt00 <- melt(Aid_00s, id.vars = c("Country.Name","Program.Name"), variable.name = "Year", value.name = "Dollars") ``` * dcast ```R #還原上個例子 cast00 <- dcast(melt00, Country.Name + Program.Name ~ Year, value.var = "Dollars") ``` ## Tidyverse的整理資料 ### 合併橫列與直行 與上節相似的函數為`bind_rows, bind_cols` ```R >require(dplyr, tibble) >SL <- tibble(sport= c("Hockey", "baseball", "football"), league = c("NHL", "MLB", "NFL")) >trophy <- tibble(trophy = c("Stanley Cup","Commissioner's Trophy", "Vince Lombardi Trophy")) >tro1 <- bind_cols(SL, trophy) >tro2 <- tribble(~sport, ~league, ~trophy, "Basketball", "NBA", "Larry O'Brien Championship Trophy", "Golf", "PGA", "Wanamaker Trophy") >#使用tribble建立另一個tibble >troies <- bind_rows(tro1, tro2) ``` ### 使用dplyr連結資料 呈上節,來使用函數來做不同型態的連結`left_join, right_join, inner_join, full_join, semi_join, anti_join` ```R left_join(diamonds, diamonColor, by=c('color'='Color')) ``` `filter, unique`可以達到`semi_join, anti_join`的功用, 若處理資料庫時,則使用後者會是比較好的選擇。 ### 轉換資料格式 `tidyr`就像`reshape2`的進階版,`gather`類似tibble的`melt`, 而`spread`就像`dcast`。 若不想轉置的欄位,可在欄位前面加負號。 ```R emotion %>% gather(key=Type, value = Measurement, Age, BMI, React, Regulate) emoition %>% gather(key=Type, value = Measurement, -ID, -Test, -Gender) emotion %>% spread(key=Type, value = Measurement) ``` ## 字串處理 ### paste 建立字串 此函數可以放入字串外,也可使用向量化的字串 ```R > paste("Hello", "Jared", "and others") [1] "Hello Jared and others" > paste("Hello", "Jared", "and others", sep = "/") [1] "Hello/Jared/and others" ``` `collapse`會使用任意分隔符號來隔開每串文字,類似sep的概念 ### 用sprintf建立含有變數的字串 前面有提到過 ### 擷取文字 使用`stringr`套件會更容易 ```R #針對特定符號來分割文字 yearlist <- str_split(string = president$YEAR, pattern="-") #與SAS中的substr一樣的概念 str_sub(president$PRESIDENT, start=1, end=3) ``` ### 正規表示法 一種用來搜尋字串的特定語法, 因為沒辦法確定位置,只能用`str_detect` ```R >#會搜尋出含有"John"的資料, >#若要忽略大小寫,則要再增加ignore.case >str_detect(string=president$PRESIDENT, pattern="John") >str_detect(president$PRESIDENT, ignore.case("John")) ``` 若擷取後,數據前後可能會有空格,則可使用`str_trim`來移除。 若要從資料中擷取任何有含特定字串的地方,則可使用`str_extract` ```R str_extract(string=theStart, pattern="Jane") #若要搜尋四位數的數字,\\d代表任何整數(0-9) str_extract(string = theStart, "\\d{4}",20) #此為搜尋出現過一次~三次 str_extract(string = theStart, "\\d{1,3}") #^代表搜尋前端,$代表搜尋後端 str_extract(string = theStart, "^\\d{1,3}$") #可以取代文字或數字 str_replace(string = theStart, pattern ="\\d", replacement="x" ) #代表所有數字都取代成x str_replace_all(string = theStart, pattern ="\\d", replacement="x" ) ``` ## 機率分佈 ### 常態分佈(Normal Distribution) ```R >#常態分佈 rnorm(n, mean, sd) >#常態分佈的機率密度,針對特地的數值 dnorm() ``` ### 二項分佈(Binomial Distribution) ```R rbinom(n, size, prob) >#機率密度 dbinom(n, size, prob) >#累積機率 pbinom(n, size, prob) ``` ### 泊松分佈(Poisson Distribution) ```R rpois(n,lambda) ``` ## 基本統計分析 ### 摘要統計(Summary Statistics) ```R mean(), weighted.mean()#加權平均 var()#變異數 quantile(x, probs= c(0.25,0.75)) #百分位數 summary() #同時包含mean, min, max, median,NA的個數也會算在內 ``` ### 相關係數(correlation)和共變異數(covariace) ```R >#相關係數 cor(economics$pce, economics$psavert) >#共變異數 coveconomics$pce, economics$psavert) >#也可以時同計算多組相關係數 cor(economics[, c(2,4:6)]) >#繪製相關係數資料成對圖 GGally::ggpairs(economics[, c(2,4:6)]) ``` ![](https://i.imgur.com/lP7vqHI.png) ### 常態檢定 一般通常使用Shapiro-Wilk 常態性檢定,不用載入package即可檢定 但此函數有樣本數限制,大於5000筆數據則無法使用。 ```R shapiro.test(x) ``` 因此,也有其他檢定常態的方法, 如nortest套件中有好幾種方法 ```R >#Anderson-Darling 常態性檢定 ad.test(x) >#Cramer-von Mises 檢定 cvm.test(x) >#Lilliefors 檢定 lillie.test(x) >#Pearson Chi-Squared 檢定 pearson.test(x) >#Shapiro-Francia 檢定,樣本數>5000不可使用 sf.test(x) ``` ### T檢定 #### 變項呈現常態 ```R >#單一樣本T檢定,雙尾檢定 >#alternative:less代表左尾檢定,greater代表右尾檢定 t.test(tips$tip, alternative = "two.sided", mu=2.5) >#獨立樣本T檢定 >#檢測變異數是否相等 var.test(tips$tip) >#var.equal=TRUE代表雙樣本T檢定,若=FALSE則進行Welch檢定 t.test(tip ~sex, data=tips, var.equal=TRUE) >#成對樣本T檢定 t.test(father.son$fheight, father.son$sheight, paired=TRUE) >#三組以上檢定(anova) out <- aov(y ~ x) summary(out) >#事後檢定 >#1.Fisher's LSD library(agricolae) LSD.test(out,'x',console=TRUE) >#2.Tukey's HSD HSD.test(out,'x',console=TRUE) ``` #### 變項呈現非常態 ```R >#單一樣本檢定,使用wilcoxon signed rank test / signed test wilcox.test(x, alternative, mu = 0) >#獨立樣本檢定,使用wilcoxon rank sum test(mann-whitney u test) wilcox.test(x, y, exact=F, correct=F) >#成對樣本檢定,使用wilcoxon signed rank test wilcox.test(x,y, exact=F, correct=F, paired=T) >#三組以上檢定,使用kruskal-wallis test kruskal.test(y ~ x, data = test) ``` ### 變異數分析(ANOVA) ```R tipANOVA <- aov(tip ~day-1, tips) summary(tipANOVA) ``` ## 線性模型 ### 簡單線性回歸模型 ```R heightLM <- lm(sheight ~ fheight, data = fater.son) summary(heightLM) ``` ### 多元回歸模型 ```R housel <- lm(valuepersqft ~ units + sqft+ boro, data = housing) summary(housel) ``` 可將結果用coefplot繪製 ### forest plot森林圖 ## 存活分析 ### IRR