之前我們已經(jīng)了解了如何去提取行窿克、列數(shù)據(jù)。這部分我們講講如何篩選自己想要的數(shù)據(jù)毛甲。生統(tǒng)常見的一個數(shù)據(jù)提取問題就是年叮,提取某某處理的那部分?jǐn)?shù)據(jù)進(jìn)行一些檢驗。比如玻募,在有3種種子的數(shù)據(jù)中只损,提取出1號種子對應(yīng)的數(shù)據(jù)。這時候七咧,盡管我們可以根據(jù)1號種子的數(shù)字索引來提取改执,但這終歸不是一個好的方法,因為一旦數(shù)據(jù)是打亂的坑雅,我們就無法知道正確的數(shù)字索引辈挂,從而進(jìn)行提取了。所以裹粤,這時候终蒂,我們就應(yīng)該使用我們之前講過的邏輯運算符來進(jìn)行操作。
順便提下遥诉,我們之前在介紹數(shù)據(jù)框的時候拇泣,把行叫做觀測,而把列叫做變量矮锈。所以我們在提取行的時候霉翔,就是在提取我們感興趣的觀測,而在提取列的時候苞笨,就是在提取我們感興趣的變量债朵。為什么我要翻來覆去地說這個呢子眶,是因為我覺得以行作為觀測,列作為變量是一個比較好的呈現(xiàn)數(shù)據(jù)的方式序芦,也是后面很多我們生統(tǒng)要用到的包需要的格式臭杰。也是后面我們在說長寬數(shù)據(jù)轉(zhuǎn)換時候要再次提到的一點。我們再來看一下糖尿病人的例子谚中。
> patientID <- c(1, 2, 3, 4)
> age <- c(25, 34, 28, 52)
> diabetes <- c("Type1", "Type2", "Type1", "Type1")
> status <- c("Poor", "Improved", "Excellent", "Poor")
> patientdata <- data.frame(patientID, age, diabetes, status)
> patientdata
patientID age diabetes status
1 1 25 Type1 Poor
2 2 34 Type2 Improved
3 3 28 Type1 Excellent
4 4 52 Type1 Poor
這里是 4 行渴杆,就是 4 個觀測值,4 個病人宪塔。這里有 4 列磁奖,4 個變量,就是用 4 個不同地指標(biāo)去衡量了這些病人某筐。當(dāng)然点寥,我們也會遇見不是這樣格式的數(shù)據(jù),比如我們在第五次生統(tǒng)作業(yè)上遇見的那個用藥的數(shù)據(jù)集
> test2 <- read.table("rawdata/test2.txt",header = T)
> head(test2)
control low middle high
1 20.79 22.22 28.56 31.93
2 22.91 24.74 28.67 37.94
3 27.21 21.53 25.28 39.76
4 19.34 19.66 30.28 27.94
5 17.85 25.89 23.13 29.65
6 23.79 29.10 23.47 34.23
這個數(shù)據(jù)集是 15 行来吩,4 列敢辩。但我們并不能說我們做了 15 個觀測,應(yīng)用了 4 個變量弟疆。實際上戚长,我們根據(jù)題目可知,總共是 60 只小鼠怠苔,只用了 1 個變量同廉,即用藥的濃度。你會發(fā)現(xiàn)這個數(shù)據(jù)集的每一行都不是同一只老鼠柑司,但前面的糖尿病人數(shù)據(jù)集迫肖,每一行都是同一個病人,所以我們可以說每一行都是一個觀測攒驰。
初次學(xué) R 的人蟆湖,對于這種數(shù)據(jù)的結(jié)構(gòu)可能會感到困惑。不過不要緊玻粪,數(shù)據(jù)處理多了隅津,就會慢慢清晰起來。
順便提一下劲室,現(xiàn)在生物學(xué)的數(shù)據(jù)跟傳統(tǒng)社會學(xué)的數(shù)據(jù)有一個很大的不同就是伦仍,社會學(xué)的數(shù)據(jù)往往是低維度,高觀測很洋,而生物學(xué)的數(shù)據(jù)則恰好相反充蓝,是高維度,低觀測的。這里的維度指的就是變量谓苟。舉個例子官脓,比如你要分發(fā)問卷給別人來統(tǒng)計大家對你的產(chǎn)品感不感興趣,你可能在問卷上只有 2 個問題(2個變量娜谊,2個維度),但你卻分發(fā)給了 1w 個人(1w 個 觀測)斤讥。生物學(xué)的例子就好比纱皆,你對 100 個植株進(jìn)行了 50w 個SNP位點的分析,這里就是 100 個觀測芭商,50w 的維度派草。數(shù)據(jù)結(jié)構(gòu)的不同,就會導(dǎo)致分析方法的不同铛楣。
由于生統(tǒng)的數(shù)據(jù)列數(shù)最多也就 4,5 列近迁,加上整列的提取并不需要邏輯運算符,所以后面的提取不涉及到列的提取簸州。同時鉴竭,為了讓大家加深印象,我會交叉地用行以及觀測這兩個名詞岸浑。
利用 [] 來提取感興趣的觀測
我們之前在向量里面提到過搏存,如何提取符合條件的數(shù)據(jù),這里運用的方法也是一樣的矢洲,也是利用 which
或者 TRUE
來提取璧眠。不過在提取數(shù)據(jù)框數(shù)據(jù)的時候,我有一個小建議读虏,就是分步完成你的提取任務(wù)责静。我們還是拿糖尿病人的數(shù)據(jù)集為例子。比如我們希望提取出年齡大于 30 歲的糖尿病人的數(shù)據(jù)盖桥。
# 先得到索引
> patientdata$age > 30
[1] FALSE TRUE FALSE TRUE
> which(patientdata$age > 30)
[1] 2 4
# 把索引輸入 [] 里面
> patientdata[patientdata$age > 30,]
patientID age diabetes status
2 2 34 Type2 Improved
4 4 52 Type1 Poor
> patientdata[which(patientdata$age > 30),]
patientID age diabetes status
2 2 34 Type2 Improved
4 4 52 Type1 Poor
# 有時候嫌得到索引那步比較長灾螃,就可以把索引結(jié)果存為一個變量
> result <- patientdata$age > 30
> patientdata[result,]
patientID age diabetes status
2 2 34 Type2 Improved
4 4 52 Type1 Poor
patientdata$age > 30
提取出來的索引值順利能夠放入數(shù)據(jù)框 [] 的逗號前面是因為我們之前提到過,數(shù)據(jù)框每列是等長的揩徊。想象下睦焕,我們有 4 個觀測,我們我們用patientdata$age
提取出來的靴拱,實際上是一串有 4 個值的向量垃喊,我們對向量進(jìn)行了邏輯運算符,然后得到了 4 個 TRUE 或者 FALSE值袜炕,然后我們就可以把這些 TRUE 或者 FALSE 值和我們的觀測一一對應(yīng)本谜。從而提出我們想要的觀測。
事實上偎窘,在利用索引提取的時候乌助,我還犯了個小錯誤溜在,就是把索引輸入到了錯誤的數(shù)據(jù)框里面,但并沒有報錯他托。
> test2[result,]
control low middle high
2 22.91 24.74 28.67 37.94
4 19.34 19.66 30.28 27.94
6 23.79 29.10 23.47 34.23
8 18.53 18.64 29.62 29.13
10 20.14 25.49 34.64 36.15
12 19.36 22.69 29.22 24.07
14 24.13 20.36 35.12 35.24
這個故事告訴我們的是掖肋,索引得到的只是一串?dāng)?shù)字,他并不跟你產(chǎn)生這個索引結(jié)果的數(shù)據(jù)集有一毛錢的關(guān)系赏参。
不要認(rèn)為 R 的命令是黑箱志笼,一步步地去拆解命令缴守,你就可以很清晰地理解痛侍。
如果我們想要兩個條件呢己儒,即年齡大于30歲绸罗,且犯的是 Type I 型糖尿病呢汛骂。年齡大于 30 用的是 >
净神,I 型糖尿病用的是等于 ==
,那且是什么呢蔫饰。就是我們之前提到的與或非了酌呆。
運算符 | 描述 |
---|---|
x | y | x或y |
x & y | x和(且)y |
非的話是
!
疗锐,不等于是!=
坊谁。不過我們估計是用不到的,所以我這里也就不講了滑臊。
再次來提取我們想要的觀測
# 先得到索引
> patientdata$age > 30
[1] FALSE TRUE FALSE TRUE
> patientdata$diabetes == "Type1"
[1] TRUE FALSE TRUE TRUE
> patientdata$age > 30 & patientdata$diabetes == "Type1"
[1] FALSE FALSE FALSE TRUE
# 提取
> patientdata[patientdata$age > 30 & patientdata$diabetes == "Type1",]
patientID age diabetes status
4 4 52 Type1 Poor
我們還可以在提取我們想要的觀測的同時呜袁,提取一部分變量(列)出來
> patientdata[patientdata$age > 30,c("age","status")]
age status
2 34 Improved
4 52 Poor
利用subset來提取
前面的那番操作大家可能會感覺寫的有點長,那有沒有一些簡寫呢简珠,事實上是有的阶界。你可以利用 R 基本包的 subset
函數(shù)來進(jìn)行跟上面一模一樣的操作。
別忘了用 聋庵? 來看看這個函數(shù)
有些人可能會提到用
attach
這個函數(shù)把數(shù)據(jù)框添加到 R 的搜索路徑中膘融,但實際上我不太推薦這樣,因為一旦你要完成有許多個數(shù)據(jù)框的作業(yè)祭玉,而你又忘了detach氧映,那么很有可能造成你不同數(shù)據(jù)框的不同變量之間的混淆。
subset
第一個要輸入的參數(shù)是你的數(shù)據(jù)框脱货,第二個要輸入的參數(shù)是你對于觀測(行)的篩選岛都,可以用邏輯運算符串聯(lián),第三個可選擇輸入的是你要選擇的列(變量)振峻。跟之前一樣的篩選條件臼疫,不過這次用的是 subset
函數(shù)。
# 年齡大于30歲
> subset(patientdata, age > 30)
patientID age diabetes status
2 2 34 Type2 Improved
4 4 52 Type1 Poor
# 年齡大于30扣孟,且 I 型糖尿病
> subset(patientdata, age > 30 & diabetes == "Type1")
patientID age diabetes status
4 4 52 Type1 Poor
# 年齡大于30烫堤,且 I 型糖尿病的病人的年齡和病情
> subset(patientdata, age > 30 & diabetes == "Type1",c("age","status"))
age status
4 52 Poor