1. 程式人生 > >第二章第二節 R語言因子與列表

第二章第二節 R語言因子與列表

     R語言的因子實現統計功能,因此稱為R語言的先鋒不為過份。因子用以資料分類,它有兩個內容,一是資料,二是資料的分類,稱為水平levels。列表類似C語言的結構struct,元素可選擇任意資料結構,是R語言資料結構在型別上的“開拓”。

2.4.1 因子factor

分類變數刻畫資料的細分屬。統計分析常用分類,R中稱為因子(factor)。因子應用統計學的名義變數(nominal variable)和有序變數,功能是記載資料的分組和分類,是R語言統計功能的基礎。因子有輔助資訊水平(levels)作為分類集合,因子的元素是不同值的levels集元素。水平可為分類設定有意義的標籤。

因子的水平是分類資訊,然而分類並不表示有序,例如:疾病有迴圈系統、肺部、消化系統疾病,沒有先後、程度、輕重的區別,稱為名義型類別變數。而人的健康有疾病、疲勞(亞健康)、健康、身體素質好,這四種程度是有順序的。因此因子具有普通因子和有序因子兩個型別。

應用因子生成更有意義的summary()統計資訊。

1.建立因子

    函式factor()建立資料集所有元素的分類。為資料框建立因子是良好的程式設計習慣,建立向量的因子的標準格式:

    factor(vector,levels=c(),ordered=TRUE)

引數levels定義水平集合,是一個整數向量,ordered表示有序分類,區分普通因子和有序因子。

eg1.建立向量的因子

>dv1=c(1,10,13,10)

>df1=factor(dv2)   #factor()將dv1向量的元素進行分類,建立因子df1

>df1   

[1] 1 10 13 10   #因子的元素

levels: 1 10 13   #levels集

>str(df1)    #df1的內部結構

 Factor w/3 levels:”1” “10” “13”:1 2 3 2  #分成三類:1,10,13  

    as.factor()可將資料轉換為因子。

2.資料管理

     length()是因子的長度,儲存因子元素的數量而不是levels集的數量。

3.因子的操作

(1)設定有意義的levels集元素

當一個向量不允許有重複值時,因子可以檢視分類的錯誤。

eg2.1 levels()提取水平的名稱

>pain=c(0,3,2,2,1)  #《R語言統計入門》p15的例子,對醫學資料的操作

>fpain=factor(pain,levels=0:3)  #建立pain的因子,水平的編碼0:3

>levels(fpain)=c("none","mild","medium","severe")

以上例題為因子fpain的水平設定有意義的標籤,則fpain的元素將用標籤代替。

(2)因子元素與分類的關係

eg2.2 因子的操作

>fpain

[1] none severe medium medium mild

Levels: none mild medium severe

>as.numeric(fpain)  #將fpain的元素轉換為整數

[1] 1 4 3 3 2       #數值從1開始

>levels(fpain)

[1] "none","mild","medium","severe"

以上程式表明as.numeric()只能轉換因子fpain的元素,卻不能處理levels集。

(3)分類水平的合併

    若某一個分類的觀測少不能有效統計,則將兩個水平合併到一個新的因子水平中。

>ftpain1=fpain

>levels(fpain)=list(none="none",

                intermediate=c("mild","medium"),

                severe="severe")   #合併分類用列表實現

>levels(fpain)

[1] "none","intermediate","severe"

(4)有序因子

eg3.建立醫學資料的有序因子

>patientID=c(1,2,3,4)  #每個病人的ID號不同

>statu=c(“Poor”,”Excellent”,”Improved”,”Improved”)         #病情

>patientdata=data.frame(patientID,statue)  #先建立資料框,再建立因子

>fstat=factor(statu,levels=c(“Poor”,”Improved”,”Excellent”),ordered=TRUE)

                          #有序因子,詞語是有序的

>str(fstat)

 ord.factor w/ 3 levels "Poor"<"Improved"<..: 1 3 2 2  #”<”表示有序因子

>patiendata$fstat=fstat

> summary(patientdata)  #summary()中可知每個分類的元素數量

   patientID          status        fstatu  #有序因子

 Min.   :1.00     Excellent:1      Poor    :1    #有一個病人情況不好

 1st Qu.:1.75      Improved :2     Improved :2    #兩個病人病情好轉

 Median :2.50     Poor    :1      Excellent:1    #有一個病人幾乎痊癒

 Mean   :2.50                             

 3rd Qu.:3.25                             

 Max.   :4.00

> unclass(patientdata)

$patientID

[1] 1 2 3 4

$status??????????

[1] Poor   Excellent Improved  Improved

Levels: Excellent Improved Poor

$fstat

[1] Poor   Excellent Improved  Improved

Levels: Poor < Improved < Excellent

引數ordered很有意義,應掌握使用方法。

3.因子的應用

(1)資料框設定因子變數

在資料框中生成重要的變數的因子,為接下來的資料分析做好準備。

將ISwR軟體包的醫學資料集thuesen的血糖含量設定分類{1,2,3,4,5,6,7,8,9,10,11,12},1對應[0,1.0)的變數值,...,12對應[11.0,12.0)。瞭解血糖的範圍可用函式range()。源程式見eg4.

eg4.設定資料框變數的因子

>library(ISwR)

>data(thuesen)

>dim1=dim(thuesen)

>dim1

[1] 24  2

>thuesen

##          blood.glucose  short.velocity

##1           15.3           1.76

##2           10.8           1.34

##3            8.1           1.27

##4           19.5           1.47

##5            7.2           1.27

##6            5.3           1.49

##7            9.3           1.31

##8           11.1           1.09

##9            7.5           1.18

##10          12.2           1.22

##11           6.7           1.25

##12           5.2           1.19

##13          19.0           1.95

##14          15.1           1.28

##15           6.7           1.52

##16           8.6            NA

##17           4.2           1.12

##18          10.3           1.37

##19          12.5           1.19

##20          16.1           1.05

##21          13.3           1.32

##22           4.9           1.03

##23           8.8           1.12

##24           9.5           1.70

>range(thuesen[1])

[1]  4.2  19.5

>levels=seq(4,20,1)  #4,20是range的整數

>levl=length(levles)

>ln=dim1[1]

>fthues=factor(1:ln,levels)

>fthues

##[1] <NA> <NA> <NA> 4    5    6    7    8    9    10   11   12   13   14 

##[15] 15   16   17   18   19   20   <NA> <NA> <NA> <NA>

Levels: 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

> typeof(fthues) #資料型別

[1] "integer"

> class(fthues)  #型別

[1] "factor"

> str(fthues)  #fthues內部結構

 Factor w/ 16 levels "4","5","6","7",..: 12 7 5 16 4 2 6 8 4 9 ...

                  #可用迴圈語句實現而不是簡單羅立

>for(i in 1:levl-1)    #i是向量levels的下標,不可與levels元素的值混淆

                  #i=1,levels[i]=4;i=2,levels[i]=5

logthes=thuesen$blood.glu<levels[i+1]$thuesen$blood.glu>=levels[i]

                  #logthes是邏輯向量,表示下標有效的邏輯值

                  #levels[levl]=20是為程式設計設定的一個值,無實際意義

fthues[logthes]=levels[i] 

                  #fthues[logthes]不等於levels的下標i,應仔細不可疏忽

}

>fthues

##[1] 15 10 8  19 7  5  9  11 7  12 6  5  19 15 6  8  4  10 12 16 13 4  8  9

##Levels: 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

>fthues=factor(fthues,levels=seq(4,19,1),ordered=TRUE)

>str(fthues)

 ord.factor w/ 16 levels "4"<"5"<"6"<"7"<..: 12 7 5 16 4 2 6 8 4 9 ...

>thuesen$fthues=fthues 

>summary(thuesen)

 blood.glucose      short.velocity      fthues    #因子fthues頻數的統計

 Min.   : 4.200     Min.   :1.030       8      : 3 

 1st Qu.: 7.075      1st Qu.:1.185        4      : 2 

 Median : 9.400     Median :1.270       5      : 2 

 Mean   :10.300    Mean   :1.326     6      : 2 

 3rd Qu.:12.700     3rd Qu.:1.420       7      : 2 

 Max.   :19.500     Max.   :1.950     9      : 2 

                      NA's   :1       (Other):11   

對資料框的變數設定因子,可用summary()統計每一類的元素數量,並且可應用tapply()函式對每一個進行相同的計算f()。

(2)線性迴歸的應用

因子線上性迴歸函式的資料擬閤中應用,使得輸出變短。因子的統計資訊可用匯總統計函式summary()表示。函式summary()體現資料框所有變數的彙總資訊,顯示數值連續型變數的最小值、最大值、均值和各四分位數,factor變數各水平的頻數值。因此,因子變數的應用線上性迴歸函式lm()的統計資訊中,可使輸出更短小精悍。

>summary(thuesen)

4.因子的函式

unclass()顯示因子的分類,而且有attr()等。

>unclass(df1)

[1] 1 2 3 2

>unclass(fthues)

>unclass(pathtiendata$fstatu)

5.tapply()應用和factor因子

eg5. tapply(data,index,f())的應用

> ages <-c(26,28,56,38,25,42) 

> affits <-c("R","D","D","R","U","D")  #用途類似levels,但是沒有生成factor

>tapply(ages,affits,means)  #應用affits對ages向量進行分類,計算每類的means

     D     R    U

    42    32   25

函式tapply()把向量affits當作因子,levels={"D","R","U"},”D”出現在下標2,3,6的位置,”R”出現在1,4的位置,”U”出現在5。因此,ages向量的分組是(26,55,42),(25,37),(21)。然後,tapply()對所有分組計算means均值,分別是41,31,21。此程式設計方法是對資料設定向量作為因子,因此並不是根據資料的可管理特性應用factor()進行分類,而是根據實際應用的要求。不能用factor()對向量元素進行分類時可用此方法,但是對大量資料設定每個元素的分類則很費力,例如ISwR軟體包的thuesen資料集。

函式tapply()的功能是,根據分類向量levels分組資料向量data,可得到多個分組資料,然後對所有分組應用函式f()。因此tapply()函式可不需要對資料框的不同變數應用計算f(),而是對不同長度的分組資料應用計算f()。 

2.4.2 列表list

列表(list)像C的結構struct或python語言的字典型別。列表的元件(components)稱為分量或元素,元件名則為標籤tags。R語言資料框和麵向物件程式設計的基礎是列表。列表元素的長度可不相同,型別可是單元素或者列表,因此在遞迴型recursive資料結構的基礎上看,列表是資料結構中的廣義表。

1. 建立列表

    函式list()建立不同部件組成的列表,分量可以是不同型別和長度的向量、矩陣、資料框、列表。列表是R語言多數函式的返回值型別,因此R語言函式可返回多個值組成一個列表,與C語言不同。list()的標準格式:

    list(tag1=compon1,tag2=compon2,...,tagR=componR)

    列表的常用應用有多維陣列的標籤,新增資料框的觀察,以及構成實際的報表格式。建立列表還可用函式vector(),引數mode=list。

eg1.三維陣列標籤的產生

      dim1=c(“A1”,”A2”,”A3”)

      dim2=c(“B1”,”B2”)

      dim3=c(“C1”,”C2”,”C3”)

      dimnames=list(dim1,dim2,dim3)

eg2.列表構成的報表

      報表名稱:一個字串,gs=”This is 2016 fist list”

      報表的主要物件:一個數值型向量,ha=c(20,29,39,43)

      報表的主要內容:一個矩陣,salaryM=matrix(1:10,nrow=5)

      報表的註釋:一個字元型向量,notes=c(“one”,”two”,”three”)

則,生成報表,dlist1=list(Title=gs,age=ha,salaryM,notes)。

只有前兩個元件有標籤。元件的編號又稱為索引。? 

eg3.用vector()建立列表,因為列表是向量。

>dlist2=vector(mode=list)

>dlist2[["events"]]=c("writing Docx ","studying","research")

>dist2

$events

[1]  "writing Docx"  "studying"   "research" 

2.資料管理

    資料型別 mode()、列表元件個數 length()、獲得標籤 names()。

3.列表元件的訪問

   選取列表元件的方法有三個,list$標籤,list[["標籤"]],list[[元件編號]]。若要訪問分量中的元素,則用list[[元件編號]][元素下標範圍s:t]或list$[元件名][s:t]。元素下標範圍同樣可用條件選擇的方法。

>dlist2[[1]]

[1]  "writing Docx"  "studying"   "research" 

>dlist2[[1]][2:3]

[1]  "studying"   "research" 

4.資料操作

(1)增加列表元件

方法一,元件賦值dlist2$timecha=c("Lqm","Lih","Sh"),方法二,元件下標索引賦值dlist2[[3]]=c(20,20,20,100,100,30),則列表dlist2有三個元件。

(2)刪除列表元素

    將列表元件設定為NULL,應注意此元素後面元件的下標索引都減1。

(3)生成子列表[]

    用list["標籤"]和list[元件編號]返回子列表,而list[[]]訪問元件,返回元件的型別。

>dlist3=dlist2[2]   #此方法類似資料框[列下標]

>class(dlist3)

[1]  "list"

>dlist3

$timecha

[1]  "Lqm"  "Lih"  "Sh"

(4)c()拼接合並多個列表

   然而c()合併的列表中,元件的層次相同。若要保持元件是一個列表,應用list()更恰當。

>dlist4=c(list("tomorrow",2016-10-19,5),list(read,writing))  

>class(dlist4)

[1]  "list"

>length(dlist4)

[1] 5

>dlist4

>str(dlist4)

>dlist5=list(list("tomorrow",2016-10-19,5),list(read,writing))

>str(dlist5)

5.列表的函式

(1)unlist()

    unlist()把列表轉換為向量,獲取列表的值,而且此向量的元素有標籤。去掉元素標籤用函式unnames()。若列表元素是字串則unlist()的返回值是字串,若列表元素都是數值型則產生數值向量。若兩類元素都有或者列表元素型別不同,則執行強制轉換,生成大多數元素的型別,例如字串。

>dv1=unlist(dlist4)

>class(dv1)

[1] character

>length(dv1)

[1] 5    

6.應用apply族函式 

7.型別轉換

is.recursive(x)可判斷列表是否遞迴型別。Is.list()可發現函式的返回值是否列表。as.list()轉換產生列表。