注:根據(jù)張敬信老師的《R語言編程—基于tidyverse》一書橄仆,所作筆記。
第一章 基礎(chǔ)語法
本章將學(xué)習(xí)R 語言基本語法耳奕,也是與其他編程語言相通的部分绑青,包括:搭建R 環(huán)境、常用數(shù)據(jù)類型(數(shù)據(jù)結(jié)構(gòu))屋群、控制結(jié)構(gòu)(分支闸婴、循環(huán))、自定義函數(shù)芍躏。
1.1 搭建R 環(huán)境及常用操作
1.1.1 搭建R 環(huán)境
- 安裝R
從R語言的官網(wǎng)The R Project for Statistical Computing下載R安裝包邪乍,根據(jù)自己的操作系統(tǒng),下載相應(yīng)的最新版安裝即可对竣。linux推薦conda安裝庇楞,可以管理不同的R版本,更好處理依賴關(guān)系否纬。 - 安裝RStudio
從RStudio官網(wǎng)下載安裝RStudio: 桌面版吕晌,服務(wù)器版。
1.1.2 常用操作
- 安裝包
擴展包(package)临燃,簡稱包睛驳。通常R 包都來自CRAN,審核比較規(guī)范嚴(yán)格膜廊,包的質(zhì)量相對更有保障乏沸。建議使用命令安裝:
install.packages("openxlsx")
Github 也是R 包的較大的來源,有些作者自己開發(fā)的R 包只放在Github爪瓜,也有很多CRAN R 包的最新開發(fā)版都位于Github. 可以先安裝devtools 或remotes 包蹬跃,再用其install_github() 安裝Github 來源的包:
devtools::install_github("tidyverse/dplyr") # 或者
remotes::install_github("tidyverse/dplyr")
若網(wǎng)絡(luò)等原因,導(dǎo)致直接從Github 安裝包失敗铆铆,也可以將整個包文件夾從網(wǎng)頁下載下來炬转,解壓縮到當(dāng)前路徑(或提供完整路徑),再從本地安裝它:
install.packages("dplyr-master", repos=NULL, type="source")
另外算灸,生信領(lǐng)域在R 中自成一派扼劈,有專門的包的大本營:bioconductor,先安裝BiocManager 包菲驴,再用install() 函數(shù)安裝bioconductor 來源的包:
BiocManager::install("openxlsx")
- 加載包
library(openxlsx)
- 更新包
update.packages("openxlsx")
update.packages() # 更新所有包
- 刪除包
remove.packages("openxlsx")
- 獲取或設(shè)置當(dāng)前路徑
getwd()
setwd("D:/R-4.1.1/tests")
- 賦值
R 標(biāo)準(zhǔn)語法中賦值不是用= 荐吵,而是<- 或->
x <- 1:10
x + 2
#[1] 3 4 5 6 7 8 9 10 11 12
R 也允許用= 賦值,建議用更現(xiàn)代和簡潔的= 賦值。 - 基本運算
數(shù)學(xué)運算:
+ - * /先煎、^ (求冪) 贼涩、%% (按模求余1) 、%/% (整除)
比較運算:
>薯蝎、<遥倦、>=、<=占锯、==袒哥、!=
identical(x,y)—— 判斷兩個對象是否嚴(yán)格相等;
all.equal(x,y) 或dplyr::near(x,y)——判斷兩個浮點數(shù)是否近似相等(誤差1.5e?8)
0L == 0
## [1] TRUE
identical(0L, 0)
## [1] FALSE
sqrt(2)^2 == 2
## [1] FALSE
identical(sqrt(2)^2, 2)
## [1] FALSE
all.equal(sqrt(2)^2, 2)
## [1] TRUE
dplyr::near(sqrt(2)^2, 2)
## [1] TRUE
邏輯運算:
| (或) 消略, & (與) 堡称,! (非) ,xor() (異或)
&& 和|| 是短路運算艺演,即遇到TRUE (FALSE) 則返回TRUE (FALSE) 而不繼續(xù)往下計算却紧;而& 和| 是向量運算符,對向量中所有元素分別進行運算胎撤。
- 基本數(shù)據(jù)類型
R 中的基本數(shù)據(jù)類型包括:
numeric——數(shù)值型晓殊,又分為integer (整數(shù)型) 和double (浮點型)
logical——邏輯型,只有TRUE 和FALSE伤提,或T 和F
character——字符型挺物,引號括起來的若干字符
R 中用NA 表示缺失值,NULL 表示空值飘弧,NaN 表示非數(shù),Inf 表示無窮大
對于R 中大多數(shù)函數(shù)砚著,NA 具有傳染性次伶,即NA 參與的運算,結(jié)果會變成NA
R 中注釋一行代碼用#
可用函數(shù)class(x) / typeof(x) / mode(x) 查看對象x 的類型
在展現(xiàn)數(shù)據(jù)的細節(jié)上稽穆,mode() < class() < typeof()
str(x) 顯示對象x 的結(jié)構(gòu)
- 保存和載入數(shù)據(jù)
save(x, file = "datas/dat.Rda")
load("datas/dat.Rda")
- 清屏和清除內(nèi)存變量
Ctrl + L 或單擊命令窗口右上角的小刷子可對命令窗口清屏冠王。
若要清除當(dāng)前變量,用:
rm(x) # 清除變量x
rm(list = ls(all = TRUE)) # 清除所有當(dāng)前變量
注:單擊Environment 窗口的小刷子也是清除所有當(dāng)前變量舌镶。 - 獲取幫助
編程語言最好的學(xué)習(xí)資料就是幫助柱彻。
函數(shù)幫助
命令窗口執(zhí)行:?plot
?plot - R Script 與R Project
R 腳本是單個可執(zhí)行的R 代碼文件,后綴名為.R餐胀,單擊New File 按鈕哟楷,選擇R Script,或使用快捷鍵Ctrl + Shift + N, 則新建R 腳本否灾。
R 腳本中都是可執(zhí)行的R 代碼+ 注釋卖擅,選中部分代碼,點擊Run 運行選中的代碼。
R 項目(Project)是完成某個項目或任務(wù)的一系列文件的合集(文件夾) 惩阶,包括數(shù)據(jù)文件挎狸、若干R腳本及其他附件,其中包含一個*.Rproj 文件断楷;
強烈建議使用R 項目锨匆,它能方便系統(tǒng)地管理服務(wù)于共同目的一系列的文件,可以方便移動位置甚至是移到其他電腦冬筒,而不需要做任何路徑設(shè)置就能成功運行恐锣。 - Rmarkdown
后綴名為.Rmd 的交互式文檔,是markdown 語法與R 腳本的結(jié)合账千,可以將可執(zhí)行R 代碼和不可執(zhí)行的文字?jǐn)⑹鼋拿桑跒橐粋€文件。
1.2 數(shù)據(jù)結(jié)構(gòu)I:向量匀奏、矩陣鞭衩、多維數(shù)組
數(shù)據(jù)結(jié)構(gòu)是為了便于存儲不同類型的數(shù)據(jù)而設(shè)計的數(shù)據(jù)容器。
R 中常用的數(shù)據(jù)結(jié)構(gòu)可劃分為:
同質(zhì)數(shù)據(jù)類型(homogeneous) 娃善,即所存儲的一定是相同類型的元素论衍,包括向量、矩陣聚磺、多維數(shù)組坯台;
異質(zhì)數(shù)據(jù)類型(heterogeneous) ,即可以存儲不同類型的元素瘫寝,這大大提高了存儲的靈活性蜒蕾,但同時也降低了存儲效率和運行效率,包括列表焕阿、數(shù)據(jù)框咪啡。
另外,還有字符串暮屡、日期時間數(shù)據(jù)撤摸、時間序列數(shù)據(jù)、空間地理數(shù)據(jù)等褒纲。
向量都有兩個屬性:type (類型) 准夷、length (長度) ;還能以屬性的方式向向量中任意添加額外的metadata (元數(shù)據(jù)) 莺掠,屬性可用來創(chuàng)建擴展向量衫嵌,以執(zhí)行一些新的操作。常用的擴展向量有:
- 基于整數(shù)型向量構(gòu)建的因子
- 基于數(shù)值型向量構(gòu)建的日期和日期時間
- 基于數(shù)值型向量構(gòu)建的時間序列
- 基于列表構(gòu)建的數(shù)據(jù)框和tibble
1.2.1 向量(一維數(shù)據(jù))
向量是由一組相同類型的原始值構(gòu)成的序列彻秆,可以是一組數(shù)值渐扮、一組邏輯值论悴、一組字符串等。
常用的向量有:數(shù)值向量墓律、邏輯向量膀估、字符向量。
- 數(shù)值向量
數(shù)值向量就是由數(shù)值組成的向量耻讽,單個數(shù)值是長度為1 的數(shù)值向量
x = 1.5
x
## [1] 1.5
可以用numeric() 來創(chuàng)建一個全為0 的指定長度的數(shù)值向量:
numeric(10)
## [1] 0 0 0 0 0 0 0 0 0 0
R 中經(jīng)常用函數(shù)c() 實現(xiàn)將多個對象合并到一起:
c(1, 2, 3, 4, 5)
## [1] 1 2 3 4 5
c(1, 2, c(3, 4, 5)) # 將多個數(shù)值向量合并成一個數(shù)值向量
## [1] 1 2 3 4 5
創(chuàng)建等差的數(shù)值向量察纯,用: 或者函數(shù)seq() ,基本格式為:
seq(from, to, by, length.out, along.with, ...)
from:設(shè)置首項(默認(rèn)為1) 针肥;
to:設(shè)置尾項饼记;
by:設(shè)置等差值(默認(rèn)為1 或-1) ;
length.out:設(shè)置序列長度慰枕;
along.with:以該參數(shù)的長度作為序列長度具则。
1:5 # 同seq(5) 或seq(1,5)
## [1] 1 2 3 4 5
seq(1, 10, 2) # 從1 開始, 到10 結(jié)束, 步長為2
## [1] 1 3 5 7 9
seq(3, length.out=10)
## [1] 3 4 5 6 7 8 9 10 11 12
創(chuàng)建重復(fù)的數(shù)值向量用函數(shù)rep(),基本格式為:
rep(x, times,length.out, each, ...)
x:為要重復(fù)的序列具帮;
times:設(shè)置序列重復(fù)次數(shù)博肋;
length.out:設(shè)置產(chǎn)生的序列的長度;
each:設(shè)置每個元素分別重復(fù)的次數(shù)(默認(rèn)為1) 蜂厅。
x = 1:3
rep(x, 2)
## [1] 1 2 3 1 2 3
rep(x, each = 2)
## [1] 1 1 2 2 3 3
rep(x, c(2, 1, 2)) # 按照規(guī)則重復(fù)序列中的各元素
## [1] 1 1 2 3 3
rep(x, each = 2, length.out = 4)
## [1] 1 1 2 2
rep(x, each = 2, times = 3)
## [1] 1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3
- 邏輯向量
邏輯向量匪凡,是一組邏輯值(TRUE 或FALSE, 或簡寫為T 或F) 的向量。
c(1, 2) > c(2, 1) # 等價于c(1 > 2, 2 > 1)
## [1] FALSE TRUE
c(2, 3) > c(1, 2, -1, 3) # 等價于c(2 > 1, 3 > 2, 2 > -1, 3 > 3)
## [1] TRUE TRUE TRUE FALSE
除了比較運算符外掘猿,還可以用%in% 判斷元素是否屬于集合:
c(1, 4) %in% c(1, 2, 3) # 左邊向量每一個元素是否屬于右邊集合
## [1] TRUE FALSE
- 字符向量
字符(串) 向量病游,是一組字符串組成的向量,R 中單引號和雙引號都可以用來生成字符向量稠通。
"hello, world!"
## [1] "hello, world!"
c("Hello", "World")
## [1] "Hello" "World"
c("Hello", "World") == "Hello, World"
## [1] FALSE FALSE
- 訪問向量子集
即訪問向量的一些特定元素或者某個子集衬衬。注意,R 中的索引是從1 開始的改橘。
使用元素的位置來訪問:
v1 = c(1, 2, 3, 4)
v1[2] # 第2 個元素
v1[2:4] # 第2-4 個元素
v1[-3] # 除了第3 個之外的元素
也可以放任意位置的數(shù)值向量滋尉,但是注意不能既放正數(shù)又放負(fù)數(shù):
v1[c(1,3)]
v1[c(1, 2, -3)] # 報錯
訪問不存在的位置也是可以的,返回NA:
v1[3:6]
使用邏輯向量來訪問唧龄,輸入與向量相同長度的邏輯向量,以此決定每一個元素是否要被獲燃樵丁:
v1[c(TRUE, FALSE, TRUE, FALSE)]
這可以引申為‘‘根據(jù)條件訪問向量子集’’:
v1[v1 <= 2] # 同v1[which(v1 <= 2)] 或subset(v1, v1<=2)
v1[v1 ^ 2 - v1 >= 2]
which.max(v1) # 返回向量v1 中最大值所在的位置
which.min(v1) # 返回向量v1 中最小值所在的位置
- 對向量子集賦值既棺,替換相應(yīng)元素
對向量子集賦值,就是先訪問到向量子集懒叛,再賦值丸冕。
v1[2] = 0
v1[2:4] = c(0, 1, 3)
v1[c(TRUE, FALSE, TRUE, FALSE)] = c(3, 2)
v1[v1 <= 2] = 0
注意,若對不存在的位置賦值薛窥,前面將用NA 補齊胖烛。
- 對向量元素命名
可以在創(chuàng)建向量的同時對其每個元素命名:
x = c(a = 1, b = 2, c = 3)
x
## a b c
## 1 2 3
命名后眼姐,就可以通過名字來訪問向量元素:
x[c("a", "c")]
x[c("a", "a", "c")] # 重復(fù)訪問也是可以的
x["d"] # 訪問不存在的名字
獲取向量元素的名字:
names(x)
## [1] "a" "b" "c"
更改向量元素的名字:
names(x) = c("x", "y", "z")
x["z"]
## z
## 3
移除向量元素的名字:
names(x) = NULL
x
## [1] 1 2 3
- 對向量排序
向量排序函數(shù)sort(),基本格式為:
sort(x, decreasing, na.last, ...)
x:為排序?qū)ο?數(shù)值型或字符型) 佩番;
decreasing:默認(rèn)為FALSE 即升序众旗,TRUE 為降序;
na.last:默認(rèn)為FALSE趟畏,若為TRUE贡歧,則將向量中的NA 值放到序列末尾。
函數(shù)order(), 返回元素排好序的索引赋秀,以其結(jié)果作為索引訪問元素利朵,正好是排好序的向量。
函數(shù)rank()猎莲,返回值是該向量中對應(yīng)元素的‘‘排名’’绍弟。
x = c(1,5,8,2,9,7,4)
sort(x)
## [1] 1 2 4 5 7 8 9
order(x) # 默認(rèn)升序,排名第2 的元素在原向量的第4 個位置
## [1] 1 4 7 2 6 3 5
x[order(x)] # 同sort(x)
## [1] 1 2 4 5 7 8 9
rank(x) # 默認(rèn)升序著洼,第2 個元素排名第4 位
## [1] 1 4 6 2 7 5 3
1.2.2 矩陣(二維數(shù)據(jù))
矩陣是一個用兩個維度表示和訪問的向量樟遣。因此,適用于向量的性質(zhì)和方法大多也適用于矩陣:矩陣也要求元素是同一類型郭脂,數(shù)值矩陣年碘、邏輯矩陣等顶岸。
- 創(chuàng)建矩陣
函數(shù)matrix() 將一個向量創(chuàng)建為矩陣绢要,其基本格式為:
matrix(x, nrow, ncol, byrow, dimnames, ...)
x:為數(shù)據(jù)向量作為矩陣的元素;
nrow:設(shè)定行數(shù)擅腰;
ncol:設(shè)定列數(shù)莹弊;
byrow:設(shè)置是否按行填充涤久,默認(rèn)為FALSE (按列填充) ;
dimnames:用字符型向量表示矩陣的行名和列名忍弛。
matrix(c(1, 2, 3,
4, 5, 6,
7, 8, 9), nrow = 3, byrow = FALSE)
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
matrix(c(1, 2, 3,
4, 5, 6,
7, 8, 9), nrow = 3, byrow = TRUE)
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
#對矩陣的行列命名:
matrix(1:9, nrow = 3, byrow = TRUE,
dimnames = list(c("r1","r2","r3"), c("c1","c2","c3")))
## c1 c2 c3
## r1 1 2 3
## r2 4 5 6
## r3 7 8 9
#也可以創(chuàng)建后再命名:
m1 = matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9), ncol = 3)
rownames(m1) = c("r1", "r2", "r3")
colnames(m1) = c("c1", "c2", "c3")
- 訪問矩陣子集
矩陣是用兩個維度表示和訪問的向量响迂,可以用一個二維存取器[ , ] 來訪問,這類似于構(gòu)建向量子集時用的一維存取器[]细疚≌嵬可以為每個維度提供一個向量來確定一個矩陣的子集。方括號中的第1 個參數(shù)是行選擇器疯兼,第2個參數(shù)是列選擇器然遏。與構(gòu)建向量子集一樣,可以在兩個維度中使用數(shù)值向量吧彪、邏輯向量和字符向量待侵。
m1[1,2] # 提取第1 行,第2 列的單個元素
m1[1:2, 2:4] # 提取第1 至2 行姨裸,第2 至4 列的元素
m1[c("r1","r3"), c("c1","c3")] # 提取行名為r1 和r3秧倾,列名為c1 和c3 的元素
若一個維度空缺怨酝,則選出該維度的所有元素:
m1[1,] # 提取第1 行,所有列元素
m1[,2:4] # 提取所有行那先,第2 至4 列的元素
負(fù)數(shù)表示在構(gòu)建矩陣子集時可排除該位置农猬,這和向量中的用法一致:
m1[-1,] # 提取除了第1 行之外的所有元素
m1[,-c(2,4)] # 提取除了第2 和4 列之外的所有元素
注意,矩陣是一個用兩個維度表示和訪問的向量胃榕,但它本質(zhì)上仍然是一個向量盛险。因此,向量的一
維存取器也可以用來構(gòu)建矩陣子集:
m1[3:7]
## [1] 3 4 5 6 7
由于向量只包含相同類型的元素勋又,矩陣也是如此苦掘。所以它們的操作方式也相似。若輸入一個不等
式楔壤,則返回同樣大小的邏輯矩陣:
m1 > 3
## c1 c2 c3
## r1 FALSE TRUE TRUE
## r2 FALSE TRUE TRUE
## r3 FALSE TRUE TRUE
根據(jù)它就可以選擇矩陣元素或賦值:
m1[m1 > 3] # 注意選出來的結(jié)果是向量
## [1] 4 5 6 7 8 9
1.2.3 多維數(shù)組(多維數(shù)據(jù))
向量/矩陣向更高維度的自然推廣鹤啡。具體來說,多維數(shù)組就是一個維度更高(通常大于2) 蹲嚣、可訪問的向量递瑰。數(shù)組也要求元素是同一類型。
- 創(chuàng)建多維數(shù)組
函數(shù)array() 將一個向量創(chuàng)建為多維數(shù)組隙畜,基本格式為:
array(x, dim, dimnames, ...)
x:為數(shù)據(jù)向量作為多維數(shù)組的元素抖部;
dim:設(shè)置多維數(shù)組各維度的維數(shù);
dimnames:設(shè)置多維數(shù)組各維度的名稱议惰。
a1 = array(1:24, dim = c(3, 4, 2))
a1
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 13 16 19 22
## [2,] 14 17 20 23
## [3,] 15 18 21 24
也可以在創(chuàng)建數(shù)組時對每個維度進行命名:
a1 = array(1:24, dim = c(3, 4, 2),dimnames=list(c("r1","r2","r3"),c("c1","c2","c3","c4"), c("k1","k2")))
或者創(chuàng)建之后再命名
a1 = array(1:24, dim = c(3, 4, 2))
dimnames(a1) = list(c("r1","r2","r3"),c("c1","c2","c3","c4"), c("k1","k2"))
- 訪問多維數(shù)組子集
第3 個維度姑且稱為‘‘頁”
a1[2,4,2] # 提取第2 行, 第4 列, 第2 頁的元素
a1["r2","c4","k2"] # 提取第r2 行, 第c4 列, 第k2 頁的元素
a1[1,2:4,1:2] # 提取第1 行, 第2 至4 列, 第1 至2 頁的元素
a1[,,2] # 提取第2 頁的所有元素
dim(a1) # 返回多維數(shù)組a1 的各維度的維數(shù)
1.3 數(shù)據(jù)結(jié)構(gòu)II:列表慎颗、數(shù)據(jù)框、因子
1.3.1 列表(list)
列表言询,可以包含不同類型的對象俯萎,甚至可以包括其他列表。列表最大的好處就是运杭,它能夠?qū)⒍鄠€不同類型的對象打包到一起夫啊,使得可以根據(jù)位置和名字訪問它們。
- 創(chuàng)建列表
可以用函數(shù)list() 創(chuàng)建列表辆憔。不同類型的對象可以放入同一個列表中撇眯。
l0 = list(1, c(TRUE, FALSE), c("a", "b", "c"))
l0
## [[1]]
## [1] 1
##
## [[2]]
## [1] TRUE FALSE
##
## [[3]]
## [1] "a" "b" "c"
可以在創(chuàng)建列表時,為列表的每個成分指定名字:
l1 = list(A = 1, B = c(TRUE, FALSE), C = c("a", "b", "c"))
l1
## $A
## [1] 1
##
## $B
## [1] TRUE FALSE
##
## $C
## [1] "a" "b" "c"
也可以創(chuàng)建列表后再對列表成分命名或修改名字:
names(l1) = NULL # 移除列表成分的名字
names(l1) = c("x","y","z")
- 從列表中提取成分的內(nèi)容
提取列表中成分下的內(nèi)容虱咧,最常用的方法是用$熊榛,通過成分名字來提取該成分下的內(nèi)容:
l1$y
l1$m # 訪問不存在的成分m, 將會返回NULL
也可以用[[n]] 來提取列表第n 個成分的內(nèi)容,n 也可以換成成分的名字:
l1[[2]] # 同l1[["y"]]
用[[]] 提取列表中某個成分的內(nèi)容更加靈活彤钟,可用在函數(shù)調(diào)用中来候,通過參數(shù)來傳遞成分名字:
p = "y" # 想要提取其內(nèi)容的成分名字
l1[[p]]
- 提取列表子集
經(jīng)常也需要從列表中提取多個成分及其內(nèi)容跷叉,由這些成分組成的列表構(gòu)成了原列表的一個子集逸雹。就像提取向量和矩陣的子集一樣营搅,提取一個列表子集是用[],可以取出列表中的一些成分梆砸,作為一個新的列表转质。[] 中可以用字符向量表示成分名字,用數(shù)值向量表示成分位置帖世,或用邏輯向量指定是否選擇休蟹,來取出列表成分。
l1["x"] # 同l1[1]
l1[c("x", "z")] # 同l1[c(1, 3)], l1[c(TRUE, FALSE, TRUE)]
用[] 提取若干成分時日矫,返回列表的子集赂弓,還是一個列表;用[[ ]] 提取單個成分的元素哪轿,返回的是對應(yīng)成分的元素盈魁。總之窃诉,[] 提取對象的子集杨耙,類型仍是該對象;[[]] 提取對象的內(nèi)容(下一級元素) 飘痛。
- 對列表的成分賦值
即先訪問(提取) 到列表的成分珊膜,再賦以相應(yīng)的值。注意宣脉,若給一個不存在的成分賦值车柠,列表會自動地在對應(yīng)名稱或位置下增加一個新成分。
l1$x = 0 # 將列表的成分x 賦值為0
也可以同時給多個列表成分賦值:
l1[c("x", "y")] = list(x = "new value for y", y = c(3, 1))
若要移除列表中的某些成分脖旱,只需賦值為NULL:
l1[c("z", "m")] = NULL
- 列表函數(shù)
用函數(shù)as.list() 可將向量轉(zhuǎn)換成列表:
l2 = as.list(c(a = 1, b = 2))
l2
## $a
## [1] 1
##
## $b
## [1] 2
用去列表化函數(shù)unlist()堪遂,可將一個列表打破成分界線,強制轉(zhuǎn)換成一個向量:
unlist(l2)
## a b
## 1 2
tidyverse 系列中的purrr 包為方便操作列表萌庆,提供了一系列列表相關(guān)的函數(shù)溶褪,建議讀者查閱使
用:
pluck():同[[ 提取列表中的元素
keep(): 保留滿足條件的元素
discard(): 刪除滿足條件的元素
compact(): 刪除列表中的空元素
append():在列表末尾增加元素
flatten(): 攤平列表(只攤平一層)
1.3.2 數(shù)據(jù)框(數(shù)據(jù)表)
數(shù)據(jù)框是由列向量組成、有著矩陣形式的列表践险。數(shù)據(jù)框與最常見的數(shù)據(jù)表是一致的:每一列代表一個變量屬性猿妈,每一行代表一條樣本數(shù)據(jù)。R 中自帶的數(shù)據(jù)框是data.frame巍虫,建議改用更現(xiàn)代的數(shù)據(jù)框:tibble彭则。
- 創(chuàng)建數(shù)據(jù)框
用tibble() 根據(jù)若干列向量創(chuàng)建tibble:
library(tidyverse) # 或tibble
persons = tibble(
Name = c("Ken", "Ashley", "Jennifer"),
Gender = c("Male", "Female", "Female"),
Age = c(24, 25, 23),
Major = c("Finance", "Statistics", "Computer Science"))
persons
## # A tibble: 3 x 4
## Name Gender Age Major
## <chr> <chr> <dbl> <chr>
## 1 Ken Male 24 Finance
## 2 Ashley Female 25 Statistics
## 3 Jennifer Female 23 Computer Science
用tribble() 按行錄入數(shù)據(jù)式創(chuàng)建tibble:
tribble(
~Name, ~Gender, ~Age, ~Major,
"Ken", "Male", 24, "Finance",
"Ashley", "Female", 25, "Statistics",
"Jennifer", "Female", 23, "Computer Science")
用as_tibble() 將data.frame, matrix, 各成分等長度的list, 轉(zhuǎn)換為tibble。
對于不等長的列表轉(zhuǎn)化為數(shù)據(jù)框:
a = list(A = c(1, 3, 4), B = letters[1:4])
a
## $A
## [1] 1 3 4
##
## $B
## [1] "a" "b" "c" "d"
# lengths() 獲取list 中每個元的長度
map_dfc(a, `length<-`, max(lengths(a))) # map 循環(huán)參閱1.6.2 節(jié)
## # A tibble: 4 x 2
## A B
## <dbl> <chr>
## 1 1 a
## 2 3 b
## 3 4 c
## 4 NA d
df = tibble(id = 1:4,
level = c(0, 2, 1, -1),
score = c(0.5, 0.2, 0.1, 0.5))
names(df) = c("id", "x", "y")
df
## # A tibble: 4 x 3
## id x y
## <int> <dbl> <dbl>
## 1 1 0 0.5
## 2 2 2 0.2
## 3 3 1 0.1
## 4 4 -1 0.5
數(shù)據(jù)框既是列表的特例占遥,也是矩陣的推廣俯抖,因此訪問這兩類對象的方式都適用于數(shù)據(jù)框。
- 提取數(shù)據(jù)框的元素瓦胎、子集
(1) 以列表方式提取數(shù)據(jù)框的元素芬萍、子集
可以用$ 按列名來提取某一列的值尤揣,或者用[[]] 按照位置或列名提取。例如柬祠,提取列名為x 列的值北戏,得到向量:
df$x # 同df[["x"]], df[[2]]
## [1] 0 2 1 -1
以列表形式構(gòu)建子集完全適用于數(shù)據(jù)框,同時也會生成一個新的數(shù)據(jù)框漫蛔。提取子集的操作符[] 允許用數(shù)值向量表示列的位置嗜愈,用字符向量表示列名,或用邏輯向量指定是否選擇莽龟。
例如蠕嫁,提取數(shù)據(jù)框的一列或多列,得到子數(shù)據(jù)框:
df[1] # 提取第1 列, 同df["id"]
## # A tibble: 4 x 1
## id
## <int>
## 1 1
## 2 2
## 3 3
## 4 4
df[1:2] # 同df[c("id","x")], df[c(TRUE,TRUE,FALSE)]
## # A tibble: 4 x 2
## id x
## <int> <dbl>
## 1 1 0
## 2 2 2
## 3 3 1
## 4 4 -1
(2) 以矩陣方式提取數(shù)據(jù)框的元素毯盈、子集
以列表形式操作并不支持行選擇拌阴。以矩陣形式操作更加靈活,若將數(shù)據(jù)框看作矩陣奶镶,其二維形式 的存取器可以很容易地獲取一個子集的元素迟赃,同時支持列選擇和行選擇。換句話說厂镇,可以使用[i, j] 指定行或列來提取數(shù)據(jù)框子集纤壁,[ , ] 內(nèi)可以是數(shù)值向量、字符向量或者邏輯向量捺信。
若行選擇器為空酌媒,則只選擇列(所有行) :
df[, "x"]
## # A tibble: 4 x 1
## x
## <dbl>
## 1 0
## 2 2
## 3 1
## 4 -1
df[, c("x","y")] # 同df[,2:3]
## # A tibble: 4 x 2
## x y
## <dbl> <dbl>
## 1 0 0.5
## 2 2 0.2
## 3 1 0.1
## 4 -1 0.5
若列選擇器為空,則只選擇行(所有列) :
df[c(1,3),]
## # A tibble: 2 x 3
## id x y
## <int> <dbl> <dbl>
## 1 1 0 0.5
## 2 3 1 0.1
同時選擇行和列:
df[1:3, c("id","y")]
## # A tibble: 3 x 2
## id y
## <int> <dbl>
## 1 1 0.5
## 2 2 0.2
## 3 3 0.1
根據(jù)條件篩選數(shù)據(jù)迄靠。例如用y >= 0.5 篩選df 的行秒咨,并選擇id 和y 兩列:
df[df$y >= 0.5, c("id","y")]
## # A tibble: 2 x 2
## id y
## <int> <dbl>
## 1 1 0.5
## 2 4 0.5
按列名屬于集合{x, y, w} 來篩選df 的列,并選擇前兩行:
ind = names(df) %in% c("x","y","w")
df[1:2, ind]
## # A tibble: 2 x 2
## x y
## <dbl> <dbl>
## 1 0 0.5
## 2 2 0.2
- 給數(shù)據(jù)框賦值
給數(shù)據(jù)框賦值掌挚,就是選擇要賦值的位置雨席,再準(zhǔn)備好同樣大小且格式匹配的數(shù)據(jù),賦值給那些位置即可吠式,所以同樣有列表方式和矩陣方式陡厘。
(1) 以列表方式給數(shù)據(jù)框賦值
用$ 或[[ ]] 對數(shù)據(jù)框的1 列賦值
df$y = c(0.6,0.3,0.2,0.4) # 同df[["y"]] = c(0.6,0.3,0.2,0.4)
利用現(xiàn)有列,創(chuàng)建(計算) 新列:
df$z = df$x + df$y
df
## # A tibble: 4 x 4
## id x y z
## <int> <dbl> <dbl> <dbl>
## 1 1 0 0.5 0.5
## 2 2 2 0.2 2.2
## 3 3 1 0.1 1.1
## 4 4 -1 0.5 -0.5
df$z = as.character(df$z) # 轉(zhuǎn)換列的類型
df
## # A tibble: 4 x 4
## id x y z
## <int> <dbl> <dbl> <chr>
## 1 1 0 0.5 0.5
## 2 2 2 0.2 2.2
## 3 3 1 0.1 1.1
## 4 4 -1 0.5 -0.5
用[] 可以對數(shù)據(jù)框的1 列或多列進行賦值:
df["y"] = c(0.8,0.5,0.2,0.4)
df[c("x", "y")] = list(level = c(1,2,1,0),
score = c(0.1,0.2,0.3,0.4))
(2) 以矩陣方式給數(shù)據(jù)框賦值
以列表方式對數(shù)據(jù)框進行賦值時特占,也是只能訪問列糙置。若需要更加靈活地進行賦值操作,可以以矩陣方式進行是目。
df[1:3,"y"] = c(-1,0,1)
df[1:2,c("x","y")] = list(level = c(0,0),score = c(0.9,1.0))
- 一些有用函數(shù)
函數(shù)str() 或glimpse() 作用在R 對象上谤饭,顯示該對象的結(jié)構(gòu):
str(persons)
## tibble [3 x 4] (S3: tbl_df/tbl/data.frame)
## $ Name : chr [1:3] "Ken" "Ashley" "Jennifer"
## $ Gender: chr [1:3] "Male" "Female" "Female"
## $ Age : num [1:3] 24 25 23
## $ Major : chr [1:3] "Finance" "Statistics" "Computer Science"
summary() 作用在數(shù)據(jù)框/列表上,將生成各列/成分的匯總信息:
summary(persons)
## Name Gender Age
## Length:3 Length:3 Min. :23.0
## Class :character Class :character 1st Qu.:23.5
## Mode :character Mode :character Median :24.0
## Mean :24.0
## 3rd Qu.:24.5
## Max. :25.0
## Major
## Length:3
## Class :character
## Mode :character
經(jīng)常需要將多個數(shù)據(jù)框(或矩陣) 按行或按列進行合并。用函數(shù)rbind()揉抵,增加行(樣本數(shù)據(jù)) 宜岛,要求寬度(列數(shù)) 相同;用函數(shù)cbind()功舀,增加列(屬性變量) ,要求高度(行數(shù)) 相同身弊。
例如辟汰,向數(shù)據(jù)框persons 數(shù)據(jù)框中添加一個人的新記錄:
rbind(persons,
tibble(Name = "John", Gender = "Male",
Age = 25, Major = "Statistics"))
## # A tibble: 4 x 4
## Name Gender Age Major
## <chr> <chr> <dbl> <chr>
## 1 Ken Male 24 Finance
## 2 Ashley Female 25 Statistics
## 3 Jennifer Female 23 Computer Science
## 4 John Male 25 Statistics
向persons 數(shù)據(jù)框中添加兩個新列表示每個人是否已注冊和其手頭的項目數(shù)量:
cbind(persons, Registered = c(TRUE, TRUE, FALSE),
Projects = c(3, 2, 3))
## Name Gender Age Major Registered Projects
## 1 Ken Male 24 Finance TRUE 3
## 2 Ashley Female 25 Statistics TRUE 2
## 3 Jennifer Female 23 Computer Science FALSE 3
rbind() 和cbind() 不會修改原始數(shù)據(jù),而是生成一個添加了行或列的新數(shù)據(jù)框阱佛。
函數(shù)expand.grid() 可生成多個屬性水平值所有組合(笛卡兒積) 的數(shù)據(jù)框:
expand.grid(type = c("A","B"), class = c("M","L","XL"))
## type class
## 1 A M
## 2 B M
## 3 A L
## 4 B L
## 5 A XL
## 6 B XL