之前我們已經了解了如何去提取行、列數據。這部分我們講講如何篩選自己想要的數據。生統常見的一個數據提取問題就是,提取某某處理的那部分數據進行一些檢驗。比如,在有3種種子的數據中,提取出1號種子對應的數據。這時候,盡管我們可以根據1號種子的數字索引來提取,但這終歸不是一個好的方法,因為一旦數據是打亂的,我們就無法知道正確的數字索引,從而進行提取了。所以,這時候,我們就應該使用我們之前講過的邏輯運算符來進行操作。
順便提下,我們之前在介紹數據框的時候,把行叫做觀測,而把列叫做變量。所以我們在提取行的時候,就是在提取我們感興趣的觀測,而在提取列的時候,就是在提取我們感興趣的變量。為什么我要翻來覆去地說這個呢,是因為我覺得以行作為觀測,列作為變量是一個比較好的呈現數據的方式,也是后面很多我們生統要用到的包需要的格式。也是后面我們在說長寬數據轉換時候要再次提到的一點。我們再來看一下糖尿病人的例子。
> 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 個不同地指標去衡量了這些病人。當然,我們也會遇見不是這樣格式的數據,比如我們在第五次生統作業上遇見的那個用藥的數據集
> 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
這個數據集是 15 行,4 列。但我們并不能說我們做了 15 個觀測,應用了 4 個變量。實際上,我們根據題目可知,總共是 60 只小鼠,只用了 1 個變量,即用藥的濃度。你會發現這個數據集的每一行都不是同一只老鼠,但前面的糖尿病人數據集,每一行都是同一個病人,所以我們可以說每一行都是一個觀測。
初次學 R 的人,對于這種數據的結構可能會感到困惑。不過不要緊,數據處理多了,就會慢慢清晰起來。
順便提一下,現在生物學的數據跟傳統社會學的數據有一個很大的不同就是,社會學的數據往往是低維度,高觀測,而生物學的數據則恰好相反,是高維度,低觀測的。這里的維度指的就是變量。舉個例子,比如你要分發問卷給別人來統計大家對你的產品感不感興趣,你可能在問卷上只有 2 個問題(2個變量,2個維度),但你卻分發給了 1w 個人(1w 個 觀測)。生物學的例子就好比,你對 100 個植株進行了 50w 個SNP位點的分析,這里就是 100 個觀測,50w 的維度。數據結構的不同,就會導致分析方法的不同。
由于生統的數據列數最多也就 4,5 列,加上整列的提取并不需要邏輯運算符,所以后面的提取不涉及到列的提取。同時,為了讓大家加深印象,我會交叉地用行以及觀測這兩個名詞。
利用 [] 來提取感興趣的觀測
我們之前在向量里面提到過,如何提取符合條件的數據,這里運用的方法也是一樣的,也是利用 which 或者 TRUE 來提取。不過在提取數據框數據的時候,我有一個小建議,就是分步完成你的提取任務。我們還是拿糖尿病人的數據集為例子。比如我們希望提取出年齡大于 30 歲的糖尿病人的數據。
# 先得到索引
> 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
# 有時候嫌得到索引那步比較長,就可以把索引結果存為一個變量
> result <- patientdata$age > 30
> patientdata[result,]
patientID age diabetes status
2 2 34 Type2 Improved
4 4 52 Type1 Poor
patientdata$age>30 提取出來的索引值順利能夠放入數據框 [] 的逗號前面是因為我們之前提到過,數據框每列是等長的。想象下,我們有 4 個觀測,我們我們用 patientdata$age 提取出來的,實際上是一串有 4 個值的向量,我們對向量進行了邏輯運算符,然后得到了 4 個 TRUE 或者 FALSE值,然后我們就可以把這些 TRUE 或者 FALSE 值和我們的觀測一一對應。從而提出我們想要的觀測。
事實上,在利用索引提取的時候,我還犯了個小錯誤,就是把索引輸入到了錯誤的數據框里面,但并沒有報錯。
> 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
這個故事告訴我們的是,索引得到的只是一串數字,他并不跟你產生這個索引結果的數據集有一毛錢的關系。
不要認為 R 的命令是黑箱,一步步地去拆解命令,你就可以很清晰地理解。
如果我們想要兩個條件呢,即年齡大于30歲,且犯的是 Type I 型糖尿病呢。年齡大于 30 用的是 > ,I 型糖尿病用的是等于 == ,那且是什么呢。就是我們之前提到的與或非了。
運算符描述
x \y
x & yx和(且)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 函數來進行跟上面一模一樣的操作。
別忘了用 ?來看看這個函數
有些人可能會提到用 attach 這個函數把數據框添加到 R 的搜索路徑中,但實際上我不太推薦這樣,因為一旦你要完成有許多個數據框的作業,而你又忘了detach,那么很有可能造成你不同數據框的不同變量之間的混淆。
subset 第一個要輸入的參數是你的數據框,第二個要輸入的參數是你對于觀測(行)的篩選,可以用邏輯運算符串聯,第三個可選擇輸入的是你要選擇的列(變量)。跟之前一樣的篩選條件,不過這次用的是 subset 函數。
# 年齡大于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
作者:城管大隊哈隊長