本培訓(xùn)使用R 4.2及以上版本。
一、前言
用R分析數(shù)據(jù)得出結(jié)果,需要解決兩個(gè)問題:
用什么包/函數(shù)來處理數(shù)據(jù)?
如何整理數(shù)據(jù),使得數(shù)據(jù)可以套進(jìn)函數(shù)里進(jìn)行處理?
(一)在R中新建項(xiàng)目
方式:RStudio中,菜單欄File→NewProject→NewDirectory→NewProject→DirectoryName
該方式通過新建一個(gè)目錄的方式來新建一個(gè)項(xiàng)目,創(chuàng)建一個(gè)R的項(xiàng)目文件(Rproj):
- 將所有與該項(xiàng)目相關(guān)的數(shù)據(jù)、腳本、文件等都存放在該項(xiàng)目文件夾下,每次通過運(yùn)行Rproj文件啟動(dòng)項(xiàng)目,自動(dòng)關(guān)聯(lián)相關(guān)文件,便于統(tǒng)一管理和調(diào)試。
- 該項(xiàng)目的工作目錄即為新建該項(xiàng)目創(chuàng)建的目錄。即后續(xù)創(chuàng)建的腳本文件默認(rèn)保存位置均為該目錄。
- 項(xiàng)目目錄移動(dòng)后,項(xiàng)目中的文件、腳本仍然可以通過項(xiàng)目文件(Rproj)關(guān)聯(lián)使用。
(二)在項(xiàng)目中新建腳本
方式:Rstudio菜單欄,F(xiàn)ile→NewFile→RScript
保存:
- R腳本保存的文件后綴為.R
- 保存的默認(rèn)位置為當(dāng)前的工作目錄(working directory)
Tips:
腳本中點(diǎn)擊Run或快捷鍵ctrl+Enter,執(zhí)行光標(biāo)所在行的代碼,光標(biāo)會(huì)移動(dòng)到下一行
腳本中選中多行,點(diǎn)擊Run,執(zhí)行所選的代碼
使用#為腳本添加注釋。讓自己和其他協(xié)作者了解代碼的用途。R不會(huì)執(zhí)行#后面的內(nèi)容。
(三)與R交互的兩種方式
1. 控制臺(tái)窗口(console)
顯示每個(gè)命令的結(jié)果
2. 腳本編輯器
記錄工作代碼,讓代碼和工作流程具有可重復(fù)性。
點(diǎn)擊Run來運(yùn)行代碼
(四)程序運(yùn)行的問題指南
1. 出現(xiàn)ERROR
即報(bào)錯(cuò)。需要對(duì)癥處理。
2. 長(zhǎng)時(shí)間運(yùn)行中,并未出現(xiàn)命令提示符>
可能卡住了。點(diǎn)擊console窗口右上角紅色STOP按鈕終止程序運(yùn)行。
3. 運(yùn)行出結(jié)果、沒反應(yīng)、出現(xiàn)warning、其他提示信息,出現(xiàn)新一行的命令提示符>
目前一切順利
4. 出現(xiàn)問題
必須回答。
5. 出現(xiàn)+
代碼不完整。補(bǔ)齊代碼,或按ESC鍵退出。
二、數(shù)據(jù)類型
- 數(shù)值型(numeric)
1.3 2 - 字符型(character)
“a” “nn” - 邏輯型(logical)
TRUE(T) FALSE(F) NA
NA:為缺失值,表示存在但未知。
NULL:為空,表示沒有這個(gè)值(不存在)。
可以用函數(shù)class()來判斷數(shù)據(jù)的類型。
Tips:打出前幾個(gè)字母即出現(xiàn)提示,用上下鍵翻動(dòng),Tab鍵自動(dòng)補(bǔ)全
(一)邏輯型數(shù)據(jù)
比較運(yùn)算
比較運(yùn)算的結(jié)果是邏輯值。
比較運(yùn)算符號(hào):
<,>, >=, <=, ==(判斷是否相等), !=(判斷是否不等)
舉例:
> 3==5
[1] FALSE
> 3!=5
[1] TRUE
多個(gè)邏輯條件的連接
連接符號(hào):
& 表示和/與
| 表示或
!表示非
舉例:
> 3<5&4>5
[1] FALSE
> 3<5 | 4>5
[1] TRUE
> !(4>5)
[1] TRUE
(二)數(shù)據(jù)類型的判斷和轉(zhuǎn)換
is族函數(shù),判斷數(shù)據(jù)類型,返回值為邏輯值
is.numeric()
是否為數(shù)值型數(shù)據(jù)
is.logical()
是否為邏輯型數(shù)據(jù)is.character()
是否為字符型數(shù)據(jù)
as族函數(shù)實(shí)現(xiàn)數(shù)據(jù)類型之間的轉(zhuǎn)換
as.numeric()
將其他數(shù)據(jù)類型轉(zhuǎn)換為數(shù)值型
as.logical()
將其他數(shù)據(jù)類型轉(zhuǎn)換為邏輯型as.character()
將其他數(shù)據(jù)類型轉(zhuǎn)換為字符型
本節(jié)函數(shù)
1. class()
描述:判斷數(shù)據(jù)類型。
舉例:
> class(2)
[1] "numeric"
> class('abc')
[1] "character"
> class(FALSE)
[1] "logical"
> class(NA)
[1] "logical"
2. is.numeric()
描述:判斷是否為數(shù)值型數(shù)據(jù)
舉例:
> is.numeric("a")
[1] FALSE
> is.numeric("4")
[1] FALSE
3. is.logical()
描述:判斷是否為邏輯型數(shù)據(jù)
舉例:
> is.logical(FALSE)
[1] TRUE
4. is.character()
描述:判斷是否為字符型數(shù)據(jù)
舉例:
> is.character("4")
[1] TRUE
5. as.numeric()
描述:將其他數(shù)據(jù)類型轉(zhuǎn)換為數(shù)值型
舉例:
> as.numeric('4')
[1] 4
> as.numeric('jimmy')
[1] NA
Warning message:
NAs introduced by coercion
討論:開始講,NA表示“存在但未知”,as.numeric("jimmy")返回NA,意思是可以將Jimmy這個(gè)字符串轉(zhuǎn)換成數(shù)值類型,但是這個(gè)這個(gè)值是未知的?R轉(zhuǎn)換了類型,但不知道是個(gè)啥,所以返回了NA。NA也有數(shù)值型NA和字符型NA。
參見以下代碼:
> a <- 'jimmy'
> class(a)
[1] "character"
> a <- as.numeric(a)
Warning message:
NAs introduced by coercion
> class(a)
[1] "numeric"
6. as.logical()
描述:將其他數(shù)據(jù)類型轉(zhuǎn)換為邏輯型
舉例:
> as.logical(4)
[1] TRUE
> as.logical('a')
[1] NA
7. as.character()
描述:將其他數(shù)據(jù)類型轉(zhuǎn)換為字符型
舉例:
> as.character(4)
[1] "4"
> as.character(TRUE)
[1] "TRUE"
三、數(shù)據(jù)結(jié)構(gòu)
R語(yǔ)言中主要有4種數(shù)據(jù)結(jié)構(gòu),如下:

- 數(shù)據(jù)框約等于“表格”。數(shù)據(jù)框要求每一列只能有一種數(shù)據(jù)類型,且數(shù)據(jù)框只是R語(yǔ)言內(nèi)部的一個(gè)數(shù)據(jù),不是一個(gè)文件。
- 數(shù)據(jù)框單獨(dú)拿出來的一列是一個(gè)向量,視為一個(gè)整體。一個(gè)向量可以出自數(shù)據(jù)框的一列,也可以用代碼生成。
- 一個(gè)向量只能有一種數(shù)據(jù)類型,可以有重復(fù)值。
Tips:若打開的腳本文件是亂碼,可以將編碼修改成UTF-8來解決(File→Reopen with Encoding→UTF-8)。若還不行,則腳本文件本身可能已經(jīng)損壞。
(一)向量(vector)
向量是一維的。
I.向量的生成
1. 用函數(shù)c()集合在一起生成
舉例:
> c(2,5,6,2,9)
[1] 2 5 6 2 9
> c('a','f','md','b')
[1] "a" "f" "md" "b"
2. 生成連續(xù)的數(shù)字向量用冒號(hào)“:”
舉例:
> 1:5
[1] 1 2 3 4 5
3. 有重復(fù)的用函數(shù)rep(),有規(guī)律的序列用seq(),隨機(jī)數(shù)用rnorm()
舉例:
rep('x',times=3)
[1] "x" "x" "x"
> seq(from=3, to=21, by=3)
[1] 3 6 9 12 15 18 21
> rnorm(n=3)
[1] -1.7067961 0.6295338 -0.9499346
4. 通過組合,產(chǎn)生更為復(fù)雜的向量
舉例:
> paste0(rep('x',times=3),1:3)
[1] "x1" "x2" "x3"
II.對(duì)單個(gè)向量進(jìn)行的操作
1. 賦值
舉例:
> x <- c(1,3,5,1) #<-是規(guī)范的賦值符號(hào),快捷鍵Alt+-
> x
[1] 1 3 5 1
> x = c(1,3,5,1) #比較隨意的寫法
> x
[1] 1 3 5 1
賦值和輸出一起實(shí)現(xiàn)
舉例:
> (x <- c(1,3,5,1))
[1] 1 3 5 1
> x <- c(1,3,5,1);x
[1] 1 3 5 1
變量名稱的選擇:
不建議用函數(shù)或包的名稱。
不建議用帶引號(hào)的字符。
可以用字母和數(shù)字的組合,但是數(shù)字要在字母后面。
不能用空格,運(yùn)算符號(hào)在名稱中??梢允褂孟聞澗€。
不建議用中文作為變量名稱。
2. 計(jì)算
> x <- c(1,3,5,1);x
[1] 1 3 5 1
> x+1
[1] 2 4 6 2
> log(x)
[1] 0.000000 1.098612 1.609438 0.000000
> sqrt(x) #開方運(yùn)算
[1] 1.000000 1.732051 2.236068 1.000000
3. 進(jìn)行比較運(yùn)算,生成邏輯值向量
> x>3
[1] FALSE FALSE TRUE FALSE
> x==3
[1] FALSE TRUE FALSE FALSE
4. 初級(jí)的統(tǒng)計(jì)運(yùn)算
> max(x) #最大值
[1] 5
> min(x) #最小值
[1] 1
> mean(x) #均值
[1] 2.5
> median(x) #中位數(shù)
[1] 2
> var(x) #方差
[1] 3.666667
> sd(x) #標(biāo)準(zhǔn)差
[1] 1.914854
> sum(x) #總和
[1] 10
幾個(gè)重要的統(tǒng)計(jì)函數(shù)
> length(x) #長(zhǎng)度,即向量的元素個(gè)數(shù)
[1] 4
> unique(x) #去重復(fù),去除向量中重復(fù)的元素,只保留第一次出現(xiàn)的那個(gè)(從左到右)
[1] 1 3 5
> duplicated(x) #判斷對(duì)應(yīng)元素是否在前面(左邊)出現(xiàn)過重復(fù)。沒出現(xiàn)返回FALSE,出現(xiàn)返回TRUE。所以重復(fù)的元素,第一次出現(xiàn)返回FALSE,后面的重復(fù)都返回TRUE。
[1] FALSE FALSE FALSE TRUE
> table(x) #重復(fù)值統(tǒng)計(jì)
x
1 3 5 #第一行返回向量中的取值(去重后的向量元素)
2 1 1 #第二行返回每個(gè)元素的重復(fù)次數(shù)
> sort(x) #默認(rèn)升序排序
[1] 1 1 3 5
> sort(x,decreasing = F) #即默認(rèn)參數(shù)decreasing為FALSE
[1] 1 1 3 5
> sort(x,decreasing = T) #將decreasing改為TRUE,即降序打開,結(jié)果將按照降序排列。
[1] 5 3 1 1
本節(jié)函數(shù)
1. rep()
描述:復(fù)制參數(shù)x的值。
格式:rep(x, ...)
參數(shù):
x 為向量
... 可以為
times,若為1個(gè)元素,則表示重復(fù)x向量的次數(shù);若為長(zhǎng)度與x向量相等的向量,則表示分別重復(fù)x中各元素的次數(shù)。
length.out,指定輸出向量的長(zhǎng)度,從左至右選擇,多余的元素舍棄。
each,指定x中每個(gè)元素重復(fù)的次數(shù)。
舉例:
> rep('x',times=3)
[1] "x" "x" "x"
> rep(1:4, 2)
[1] 1 2 3 4 1 2 3 4
> rep(1:4, each = 2)
[1] 1 1 2 2 3 3 4 4
> rep(1:4, each = 2, length.out = 4)
[1] 1 1 2 2
2. seq()
描述:生成有規(guī)律的序列
格式:seq(from=... , to= ... , by=... )
參數(shù):
from,to 指定序列的起始值和最大結(jié)束值
by 指定序列的增量
也可以有l(wèi)ength.out參數(shù)指定輸出向量的長(zhǎng)度,則by通過指定的長(zhǎng)度計(jì)算得出。
舉例:
> seq(from=3, to=21, by=3)
[1] 3 6 9 12 15 18 21
3. rnorm()
描述:生成指定個(gè)數(shù)的服從正態(tài)分布的隨機(jī)數(shù),可以指定均數(shù)和標(biāo)準(zhǔn)差。
格式:rnorm(n, mean=0, sd=1)
參數(shù):
n 指定生成的隨機(jī)數(shù)的個(gè)數(shù)
mean 指定生成隨機(jī)數(shù)的平均數(shù),默認(rèn)為0
sd 指定生成隨機(jī)數(shù)的標(biāo)準(zhǔn)差,默認(rèn)為1
舉例:
> rnorm(n=3)
[1] -1.7067961 0.6295338 -0.9499346
4. paste0()與paste()
描述:將向量轉(zhuǎn)換成字符型數(shù)據(jù)后進(jìn)行連接。
格式:paste(...,sep=" ",collapse=NULL )
paste0與paste(..., sep="", cllapse=NULL)相同
參數(shù):
... 可以是1個(gè)或多個(gè)向量,當(dāng)其為1個(gè)向量時(shí),其作用相當(dāng)于函數(shù)as.character()
sep 多個(gè)向量連接時(shí),指定各元素之間的連接符號(hào),paste默認(rèn)為空格,paste0固定為空(即元素之間沒有連接符號(hào),緊密連接)
collapse 非單元素的多向量連接時(shí),將生成的多個(gè)元素合并成1個(gè)元素,并指定多元素間合并的連接符號(hào)
舉例:
> paste0(rep('x',times=3),1:3)
[1] "x1" "x2" "x3"
> paste(rep('x',times=3),1:3, sep=',')
[1] "x,1" "x,2" "x,3"
> paste(rep('x',times=3),1:3, collapse=',')
[1] "x 1,x 2,x 3"
> paste(rep('x',times=3),1:3, collapse='-')
[1] "x 1-x 2-x 3"
5. log()和sqrt()
描述:取對(duì)數(shù)運(yùn)算和開方運(yùn)算的函數(shù)
舉例:
> x <- c(1,3,5,1)
> log(x)
[1] 0.000000 1.098612 1.609438 0.000000
> sqrt(x)
[1] 1.000000 1.732051 2.236068 1.000000
6. 另外參見文中統(tǒng)計(jì)函數(shù)部分的函數(shù)介紹
探索
練習(xí)2-2,1.生成1到15之間所有偶數(shù)講解的答案是:
seq(from=2, to=15, by=2)
講解中提到,如果:
seq(from=1, to=15, by=2)
則生成1到15的奇數(shù),與題目的要求不符??梢酝ㄟ^加1變成偶數(shù),再想法去掉多出來的16這個(gè)數(shù)。這種方式比較復(fù)雜。但本著熟悉代碼的原則,我按照這種思路進(jìn)行嘗試,有以下2種方式得出相同的結(jié)果:
seq(1,15,2)c(1:7)+1 #首先取出7個(gè)奇數(shù)再變成偶數(shù)
> 1 2 4 6 8 10 12 14(seq(1,15,2)+1)c(1:7) #先將8個(gè)奇數(shù)變成偶數(shù),再取出其中7個(gè)
> 1 2 4 6 8 10 12 14
Tips:向量只允許一種數(shù)據(jù)類型存在,當(dāng)出現(xiàn)不同類型的數(shù)據(jù)時(shí),會(huì)自動(dòng)根據(jù)下圖的優(yōu)先順序進(jìn)行轉(zhuǎn)換。

III.對(duì)兩個(gè)向量的操作
1. 比較運(yùn)算,生成等長(zhǎng)的邏輯向量
> x == y
[1] FALSE FALSE TRUE FALSE
> y == x
[1] FALSE FALSE TRUE FALSE
2. 數(shù)學(xué)計(jì)算
> x + y
[1] 4 5 10 7
3. 連接
> paste(x,y,sep=",")
[1] "1,3" "3,2" "5,5" "1,6"
paste與paste0的區(qū)別見前文“本節(jié)函數(shù)”
循環(huán)補(bǔ)齊
當(dāng)兩個(gè)向量長(zhǎng)度不一致時(shí),會(huì)通過循環(huán)補(bǔ)齊的方式對(duì)照較長(zhǎng)的那個(gè)向量補(bǔ)齊運(yùn)算。

利用循環(huán)補(bǔ)齊簡(jiǎn)化代碼:
> paste0(rep("x",3),1:3)
[1] "x1" "x2" "x3"
> paste0("x",1:3)
[1] "x1" "x2" "x3"
4. 交集、并集、差集
> x;y
[1] 1 3 5 1
[1] 3 2 5 6
> intersect(x,y)
[1] 3 5
> union(x,y)
[1] 1 3 5 2 6
> setdiff(x,y) #取差集,x中有而y中沒有的元素,即并集中去掉y,???后文的半連接
[1] 1
> setdiff(y,x) #取差集,y中有而x中沒有的元素,即并集中去掉x
[1] 2 6
重點(diǎn):%in%
x %in% y #x的每個(gè)元素在y中是否存在
> x;y
[1] 1 3 5 1
[1] 3 2 5 6
> x %in% y #x的每個(gè)元素在y中存在嗎
[1] FALSE TRUE TRUE FALSE
> y %in% x
[1] TRUE FALSE TRUE FALSE
%in%返回的邏輯值向量與該符號(hào)前面向量中的每個(gè)元素一一對(duì)應(yīng)。
==與%in%的區(qū)別

當(dāng)兩個(gè)向量長(zhǎng)度不等時(shí),==會(huì)發(fā)生循環(huán)補(bǔ)齊;而%in%不適用。
==是元素對(duì)應(yīng)位置的比較,有順序的影響,%in%前后兩個(gè)向量中所有元素都會(huì)互相比較,沒有順序的影響。下圖中的問題,則應(yīng)該使用%in%而不能使用==。(即xx %in% y)

intersect()與%in%的區(qū)別
取交集會(huì)去重復(fù),而%in%取子集不會(huì)。見R_01項(xiàng)目中02_exercise.R練習(xí)第6題。
> # 6.向量g中有多少個(gè)元素在向量s中存在(要求用函數(shù)計(jì)算出具體個(gè)數(shù))?將這些元素篩選出來
#正確答案
> table(g %in% s)
FALSE TRUE
37 63
> g[g %in% s]
[1] "GFM2" "SLCO1C1" "NYNRIN" "COMMD1"
[5] "COMMD1" "AC017081.1" "RAB7A" "CASKIN2"
[9] "GGT7" "SNRPE" "RGPD3" "ZNF586"
[13] "COMMD1" "GGT7" "URB1" "RAB7A"
[17] "MPP2" "AFG3L2" "URB1" "AC104581.1"
[21] "MPP2" "SNRPE" "ARHGAP1" "ZNF461"
[25] "OR2D3" "CECR5" "SPDL1" "CLEC17A"
[29] "ZNF461" "ATG10" "ATG10" "ATG10"
[33] "SLC25A25" "SLC30A9" "SLCO1C1" "GGT7"
[37] "CASKIN2" "GSTP1" "MPP2" "NYNRIN"
[41] "INTS12" "MPP2" "RGPD3" "RGPD3"
[45] "SLC30A9" "C10orf128" "HBD" "SLC30A9"
[49] "GGT7" "HEPH" "RP5-1021I20.4" "KLHDC8A"
[53] "HBD" "ZNF586" "CECR5" "OR2D3"
[57] "LIPE" "INTS12" "LIPE" "SPDL1"
[61] "SLCO1C1" "GGT7" "CECR5"
#錯(cuò)誤使用取交集函數(shù)。
> length(intersect(g,s))
[1] 32
IV.向量篩選(取子集)
用 將TRUE對(duì)應(yīng)的值挑選出來,F(xiàn)ALSE丟棄。
> x <- 8:12
> x
[1] 8 9 10 11 12
#根據(jù)邏輯值取子集
> x[x==10]
[1] 10
> x[x<12]
[1] 8 9 10 11
> x[x %in% c(9,13)]
[1] 9
#根據(jù)位置取子集
> x[4]
[1] 11
> x[2:4]
[1] 9 10 11
> x[c(1,5)]
[1] 8 12
> x[-4] #-表示除了該位置的其他元素都取出來,只支持?jǐn)?shù)字,不支持邏輯值。邏輯值取相反用嘆號(hào)!
[1] 8 9 10 12
> x[-(2:4)]
[1] 8 12
Tips:
-(減號(hào))表示除了該位置的其他元素都取出來,只支持?jǐn)?shù)字,不支持邏輯值。邏輯值取相反用?。▏@號(hào))
重點(diǎn):
按照邏輯值:中括號(hào)里是與x等長(zhǎng)且一一對(duì)應(yīng)的邏輯值向量。
按照位置:中括號(hào)里是由x下標(biāo)組成的向量。
因此,指定向量中的具體某個(gè)元素時(shí),無論用邏輯值還是位置來指定,都必須使用向量。
下面的代碼會(huì)報(bào)錯(cuò):
> x
[1] 8 9 10 11 12
> x==10
[1] FALSE FALSE TRUE FALSE FALSE
> x[FALSE,FALSE,TRUE,FALSE,FALSE]
Error in x[FALSE, FALSE, TRUE, FALSE, FALSE] :
incorrect number of dimensions
> x[3,5]
Error in x[3, 5] : incorrect number of dimensions
報(bào)錯(cuò)中顯示維度錯(cuò)誤。向量是一維的,中括號(hào)中逗號(hào)分割表示多維度,所以報(bào)錯(cuò)。指定多維度的數(shù)據(jù)時(shí),用逗號(hào)分割。
V.修改向量中的某個(gè)(些)元素
1. 改一個(gè)元素
> x
[1] 8 9 10 11 12
> x[4] <- 40
> x
[1] 8 9 10 40 12
2. 改多個(gè)元素
> x
[1] 8 9 10 11 12
> x[c(1,5)] <- c(80,20)
> x
[1] 80 9 10 40 20
注意:修改元素就是取子集+賦值的聯(lián)合操作。
VI.簡(jiǎn)單向量作圖
> k1 = rnorm(12);k1
[1] 0.04332943 -0.75023874 0.51691113 1.10119324
[5] 1.59135095 -0.04078699 -0.65780426 0.93452471
[9] 1.44189919 0.44143937 -0.21297901 -0.25711064
> plot(k1) #作點(diǎn)圖
> k2 = rep(c("a","b","c","d"),each = 3);k2
[1] "a" "a" "a" "b" "b" "b" "c" "c" "c" "d" "d" "d"
> boxplot(k1~k2) #作箱線圖。將k1作為y軸;k2作為x軸


plot() 默認(rèn)作散點(diǎn)圖,可以指定另外的作圖形式(折線圖,點(diǎn)線圖等,詳見幫助文檔)
boxplot() 用連接指定需要作圖的數(shù)學(xué)公式中的函數(shù)和自變量(可以是組合分組變量),如:boxplot(yg1:g2)。詳見幫助文檔
(二)矩陣(matrix)
- 矩陣是二維的。
- 只允許一種數(shù)據(jù)類型。
Tips: 判斷數(shù)據(jù)結(jié)構(gòu)
- 根據(jù)生成他的函數(shù)來判斷
- 用函數(shù)class或is族函數(shù)來判斷
I.新建矩陣和取子集
矩陣取子集,不支持$符號(hào)。
#新建矩陣
> m <- matrix(1:9, nrow = 3)
> m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
#加列名
> colnames(m) <- c("a","b","c")
> m
a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
#取第2行
> m[2,]
a b c #由于加了列名,所以取出的行,會(huì)帶上對(duì)應(yīng)的列名一起輸出
2 5 8
#取第1列
> m[,1]
[1] 1 2 3
#取第2行第3列的數(shù)值,同樣會(huì)帶上對(duì)應(yīng)的列名。
> m[2,3]
c
8
#取出指定的連續(xù)的行和列。
> m[2:3,1:2]
a b
[1,] 2 5
[2,] 3 6
II.矩陣的轉(zhuǎn)置和轉(zhuǎn)換
> m
a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
#轉(zhuǎn)置
> t(m) #t函數(shù)可以將矩陣或者數(shù)據(jù)框的行和列進(jìn)行互換
[,1] [,2] [,3]
a 1 2 3
b 4 5 6
c 7 8 9
#轉(zhuǎn)換
> as.data.frame(m) #將矩陣轉(zhuǎn)換成數(shù)據(jù)框的數(shù)據(jù)結(jié)構(gòu)
a b c
1 1 4 7
2 2 5 8
3 3 6 9
重點(diǎn):
將數(shù)據(jù)框或舉證轉(zhuǎn)置之后,其數(shù)據(jù)結(jié)構(gòu)都是矩陣。
> df1
gene CHANGE score p.value
r1 gene1 up 12 0.01
r2 gene2 up 23 0.02
r3 gene3 down 50 0.07
r4 gene4 down 2 0.05
> t(df1)
r1 r2 r3 r4
gene "gene1" "gene2" "gene3" "gene4"
CHANGE "up" "up" "down" "down"
score "12" "23" "50" " 2"
p.value "0.01" "0.02" "0.07" "0.05"
> class(t(df1))
[1] "matrix" "array"
由于矩陣要求所有數(shù)據(jù)類型都相同,因此,轉(zhuǎn)置后的矩陣數(shù)據(jù)都是字符串類型。
若此時(shí)將矩陣轉(zhuǎn)換成數(shù)據(jù)框數(shù)據(jù)結(jié)構(gòu),則其數(shù)據(jù)類型依然全部為字符串類型。
> m <- as.data.frame(m)
> m
r1 r2 r3 r4
gene gene1 gene2 gene3 gene4
CHANGE up up down down
score 12 23 50 2
p.value 0.01 0.02 0.07 0.05
> class(m)
[1] "data.frame"
> class(m$r3)
[1] "character"
若強(qiáng)行將某一列轉(zhuǎn)換成數(shù)值類型,則非數(shù)值的單元格將由NA代替。
> m$r3 <- as.numeric(m$r3)
Warning message:
NAs introduced by coercion
> m
r1 r2 r3 r4
gene gene1 gene2 NA gene4
CHANGE up up NA down
score 12 23 50.00 2
p.value 0.01 0.02 0.07 0.05
- 給矩陣畫熱圖
pheatmap::pheatmap(m)

- 關(guān)閉聚類功能,使熱圖顏色與矩陣數(shù)值一一對(duì)應(yīng):
> pheatmap::pheatmap(m, cluster_rows = F, cluster_cols = F)

(三)數(shù)據(jù)框(data.frame)
- 數(shù)據(jù)框是二維的。
- 每列只允許一種數(shù)據(jù)類型,各列間的數(shù)據(jù)類型可以不相同。
I.數(shù)據(jù)框的來源
- 用代碼新建
- 由已有的數(shù)據(jù)轉(zhuǎn)換或處理得到
- 讀取表格文件
- R語(yǔ)言內(nèi)置數(shù)據(jù)
什么是熱圖?
熱圖是用顏色的深淺來表示數(shù)值的大小。
II.數(shù)據(jù)框的生成與操作
- 用函數(shù)data.frame()生成
> #新建和讀取數(shù)據(jù)框
> df1 <- data.frame(gene = paste0("gene",1:4), #每行生成一個(gè)向量,作為數(shù)據(jù)框的一列
+ change = rep(c("up","down"),each = 2), #每行代碼用逗號(hào)分隔
+ score = c(5,3,-2,-4))
> df1
gene change score
1 gene1 up 5
2 gene2 up 3
3 gene3 down -2
4 gene4 down -4
- 從文件中讀取
從CSV(逗號(hào)分隔符文件)文件中讀取數(shù)據(jù),生成數(shù)據(jù)框。函數(shù)read.csv()
> df2 <- read.csv("gene.csv") #文件gene.csv需放在當(dāng)前的工作目錄下
> df2
gene change score
1 gene1 up 5
2 gene2 up 3
3 gene3 down -2
4 gene4 down -4
- 數(shù)據(jù)框?qū)傩?/li>
> dim(df1) #dim函數(shù)查看數(shù)據(jù)框的行數(shù)和列數(shù),dim表示維度的意思
[1] 4 3
> nrow(df1) #只查看行數(shù)
[1] 4
> ncol(df1) #只查看列數(shù)
[1] 3
#查看行名和列名
> rownames(df1) #提取行名
[1] "1" "2" "3" "4"
> colnames(df1) #提取列名
[1] "gene" "change" "score"
- 數(shù)據(jù)框取子集
- 用$指定列名或列號(hào)來取數(shù)據(jù)框的某列
> df1$gene #刪掉score,按tab鍵試試
[1] "gene1" "gene2" "gene3" "gene4"
> mean(df1$score)
[1] 0.5
- 按坐標(biāo)、行列名、行列條件取子集
> ## 按坐標(biāo)
> df1[2,2]
[1] "up"
> df1[2,]
gene change score
2 gene2 up 3
> df1[,2]
[1] "up" "up" "down" "down"
> df1[c(1,3),1:2]
gene change
1 gene1 up
3 gene3 down
> #按名字
> df1[,"gene"]
[1] "gene1" "gene2" "gene3" "gene4"
> df1[,c('gene','change')] #用$取子集的列,只能取1列。用[]可以取多列。
gene change
1 gene1 up
2 gene2 up
3 gene3 down
4 gene4 down
> #按條件(邏輯值)——篩選score大于0的行
> df1[df1$score>0,] #表示行進(jìn)行篩選,列都要
gene change score
1 gene1 up 5
2 gene2 up 3
#思路拆解
> df1$score
[1] 5 3 -2 -4
> df1$score>0
[1] TRUE TRUE FALSE FALSE
> df1$score[df1$score>0]
[1] 5 3
> #篩選score > 0的基因
> df1[df1$score > 0,1]
[1] "gene1" "gene2"
> df1$gene[df1$score > 0] #用于取子集的邏輯值向量與原集對(duì)應(yīng)即可
[1] "gene1" "gene2"
#第一種方式還可以保留數(shù)據(jù)框的格式
> df1[df1$score > 0,1,drop=F]
gene
1 gene1
2 gene2
#將參數(shù)drop設(shè)置為FALSE,則只提取出對(duì)應(yīng)的字段,并保留原來的數(shù)據(jù)結(jié)構(gòu),不轉(zhuǎn)換成向量。
#第二種方式是不可以的,因?yàn)榈诙N方式首先提取出gene這一列(df1$gene)已經(jīng)是向量了,再取向量子集,仍然是向量。
#取數(shù)據(jù)框最后一列(不知道具體列數(shù))
> df1[,ncol(df1)] #函數(shù)ncol()求出數(shù)據(jù)框的總列數(shù),最后一列即為第“總列數(shù)”列。
[1] 5 3 -2 -4
#取數(shù)據(jù)框除去最后一列的其他列
> df1[,-ncol(df1)] #減號(hào)表示除去該列意外其他列
gene change
1 gene1 up
2 gene2 up
3 gene3 down
4 gene4 down
中括號(hào)里的逗號(hào),表示維度的分割。
重點(diǎn)與Tips:
- 數(shù)據(jù)框按照邏輯值取子集,TRUE對(duì)應(yīng)的行/列留下,F(xiàn)ALSE對(duì)應(yīng)的行/列丟掉。
- 用于取子集的邏輯值向量,與原集對(duì)應(yīng)即可,不必一定由原集生成。
- 數(shù)據(jù)框的修改
> #改一個(gè)格
> df1[3,3] <- 5
> df1
gene change score
1 gene1 up 5
2 gene2 up 3
3 gene3 down 5
4 gene4 down -4
> #改一整列
> df1$score <- c(12,23,50,2)
> df1
gene change score
1 gene1 up 12
2 gene2 up 23
3 gene3 down 50
4 gene4 down 2
> #增加一列
> df1$p.value <- c(0.01,0.02,0.07,0.05)
> df1
gene change score p.value
1 gene1 up 12 0.01
2 gene2 up 23 0.02
3 gene3 down 50 0.07
4 gene4 down 2 0.05
> #改行名和列名
> rownames(df1)
[1] "1" "2" "3" "4"
> colnames(df1)
[1] "gene" "change" "score" "p.value"
> rownames(df1) <- c("r1","r2","r3","r4")
> #只修改某一行/列的名
> colnames(df1)[2] <- "CHANGE"
> df1
gene CHANGE score p.value
r1 gene1 up 12 0.01
r2 gene2 up 23 0.02
r3 gene3 down 50 0.07
r4 gene4 down 2 0.05
Tips:
- 當(dāng)取用的列名為原數(shù)據(jù)框存在的列名,則賦值為修改改列內(nèi)容;當(dāng)取用的列名不存在與原數(shù)據(jù)框,則賦值為新增一列。
- 兩個(gè)數(shù)據(jù)框的連接
假設(shè)有三個(gè)數(shù)據(jù)框test1,test2,test3,如下:
> test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'),
+ blood_type = c("A","B","O","AB"))
> test1
name blood_type
1 jimmy A
2 nicker B
3 Damon O
4 Sophie AB
> test2 <- data.frame(name = c('Damon','jimmy','nicker','tony'),
+ group = c("group1","group1","group2","group2"),
+ vision = c(4.2,4.3,4.9,4.5))
> test2
name group vision
1 Damon group1 4.2
2 jimmy group1 4.3
3 nicker group2 4.9
4 tony group2 4.5
>
> test3 <- data.frame(NAME = c('Damon','jimmy','nicker','tony'),
+ weight = c(140,145,110,138))
> test3
NAME weight
1 Damon 140
2 jimmy 145
3 nicker 110
4 tony 138
merge()函數(shù)將兩個(gè)數(shù)據(jù)框按照列名稱進(jìn)行合并。指定的列名稱取交集,其余列均包含在新數(shù)據(jù)框中。如下:
> merge(test1,test2,by="name")
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
當(dāng)列名稱不同時(shí),若仍舊需要按照這兩列取交集合并,則可以具體指定兩個(gè)列名稱,如下:(注意指定的列名稱順序需與前面指定的數(shù)據(jù)框順序?qū)?yīng))
> merge(test1,test3,by.x = "name",by.y = "NAME")
name blood_type weight
1 Damon O 140
2 jimmy A 145
3 nicker B 110
merge()函數(shù)的幫助文檔:
描述:將兩個(gè)數(shù)據(jù)框按照共同的列或行的名稱進(jìn)行合并。
格式:merge(x,y, by= intersect(names(x), names(y)),
by.x= by, by.y= by, all=FALSE, all.x=all, all.y=all, sort=TRUE)
參數(shù):由上可知,默認(rèn)是取兩個(gè)數(shù)據(jù)框的共同相同名稱的列或者行?;蛘哌M(jìn)行單獨(dú)指定。默認(rèn)all=FALSE,表示只取共同列或行中相同值的內(nèi)容進(jìn)行合并,當(dāng)指定all=TRUE時(shí),取兩個(gè)數(shù)據(jù)框中指定行列的并集進(jìn)行合并,任一表中的缺失值,則用NA填充。
舉例:
> merge(test1, test2, by='name', all=T)
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
4 Sophie AB <NA> NA
5 tony <NA> group2 4.5
也可分別指定按照哪個(gè)數(shù)據(jù)框中的數(shù)據(jù)為標(biāo)準(zhǔn)進(jìn)行取值(即指定數(shù)據(jù)框中的數(shù)全部取,另一數(shù)據(jù)框數(shù)據(jù)取與之的交集。) 相應(yīng)的缺失值同樣用NA填充,如:
> merge(test1, test2, by='name', all.x = T)
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
4 Sophie AB <NA> NA
> merge(test1, test2, by='name', all.y = T)
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
4 tony <NA> group2 4.5
(四)列表(list)
列表可以裝各種數(shù)據(jù)結(jié)構(gòu)和類型。
I. 新建列表
#列表
l <- list(m1 = matrix(1:9, nrow = 3),
m2 = matrix(2:9, nrow = 2))
> l
$m1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$m2
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 3 5 7 9
II.列表取子集
> l[[2]] #列表的取子集,用兩個(gè)中括號(hào),表示取出其中的第幾個(gè)元素
[,1] [,2] [,3] [,4] #取出的是矩陣。
[1,] 2 4 6 8
[2,] 3 5 7 9
> l$m1 #也可以用$符號(hào)指定元素的名稱來取子集
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Tips:
列表取子集時(shí),用兩個(gè)中括號(hào),取出來的是指定元素本來的數(shù)據(jù)結(jié)構(gòu)。如上例中,取出的子集是矩陣。
若用1個(gè)中括號(hào),取出來的子集數(shù)據(jù)結(jié)構(gòu)仍然是列表,內(nèi)容雖然一致。
某些時(shí)候,一些函數(shù)只能對(duì)矩陣、向量等數(shù)據(jù)結(jié)構(gòu)進(jìn)行處理,而不支持列表,這時(shí)候需要嚴(yán)格區(qū)分所取出的數(shù)據(jù)結(jié)構(gòu)具體是哪一種。
> l
$m1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$m2
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 3 5 7 9
> class(l[[1]])
[1] "matrix" "array"
> class(l[1])
[1] "list"
> pheatmap::pheatmap(l[[1]]) #可以作圖
> pheatmap::pheatmap(l[1]) #報(bào)錯(cuò)
Error in dist(mat, method = distance) :
'list' object cannot be coerced to type 'double'
重要練習(xí)題:
# 3.篩選test中,Species列的值為a或c的行
test[test$Species!="b",]
test[test$Species=="a"|test$Species=="c",]
test[test$Species %in% c("a","c"),]
第三個(gè)答案反復(fù)體會(huì)。
四、函數(shù)

function為編寫函數(shù)的函數(shù)。
列出一個(gè)包里有哪些函數(shù)或數(shù)據(jù)
ls('package:stringr') #列出stringr包中有哪些函數(shù)