數據框(data.frame)是最常用的數據結構,用於存儲二維表(即關系表)的數據,每一列存儲的數據類型必須相同,不同數據列的數據類型可以相同,也可以不同,但是每列的行數(長度)必須相同。數據框的每列都有唯一的名字,在已創建的數據框上,用戶可以添加計算列,這樣,R引擎根據同一行的數據列,計算出表達式的值,並把該值作為計算列的值。數據框是數據分析中最重要的數據對象,必須熟練掌握數據框的操作。
一,創建數據框
創建數據框,常用的方式是:讀取文件、讀取關系表和使用函數創建,用戶應根據實際的需要,選擇合適的方式創建數據框。
1,讀取文件
第一種方法是通過讀取文件創建,常用的是用於讀取文件的函數是read.table(),語法是如下所示:
read.table(file, header = FALSE, sep = "", quote = "\"'", dec = ".", numerals = c("allow.loss", "warn.loss", "no.loss"), row.names, col.names, as.is = !stringsAsFactors, na.strings = "NA", colClasses = NA, nrows = -1, skip = 0, check.names = TRUE, fill = !blank.lines.skip, strip.white = FALSE, blank.lines.skip = TRUE, comment.char = "#", allowEscapes = FALSE, flush = FALSE, stringsAsFactors = default.stringsAsFactors(), fileEncoding = "", encoding = "unknown", text, skipNul = FALSE)
參數釋義:
- file:讀取數據的文件名和路徑,文件名可以是文件的絕對路徑名,或是相對路徑名,如果文件名是相對路徑名,那么文件名是基於當前的工作目錄,當前的工作目錄可以通過函數 getwd() 獲取;
- header:邏輯值,文件的第一行是否包含列名;
- sep:用於指定字段(列)的分隔符,默認值是空字符,行的分隔符是回車和換行;
- quote:字符的引用符,只有當文本使用引用符,才被視為字符,設置為空字符,禁用引用符;
- dec:小數點符號;
- check.names:邏輯值,是否檢查列名是否符合變量的命名規范;
- colClasses:用於指定列的數據類型;
- fill:邏輯值,當設置為TRUE時,如果行的列數不夠,那么填充空白的字段;
- strip.white:邏輯值,只有當sep參數指定時,用於移除字符字段兩端的空格;
- blank.lines.skip :邏輯值,當為TRUE時,跳過空白的數據行;
- encoding :字符串,用於指定字符的編碼規則,常用的編碼規則是UTF-8;
- nrows :整數值,能夠讀取的最大數據行數量;
- skip:整數值,從文件的開頭,跳過一定數量的數據行,從下一行開始讀取數據;
函數read.csv()是read.table()的包裝函數,專門用於讀取csv文件,例如:
df <- read.csv('D:/data.csv', check.names = FALSE, encoding = "UTF-8", blank.lines.skip = FALSE);
2,讀取關系表數據
第二種方法是從關系型數據庫執行SQL查詢,根據查詢結果創建數據框;當連接SQL Server數據庫時,使用ODBC驅動程序連接數據庫,R腳本引用RODBC包,調用odbcConnect連接,使用sqlQuery執行查詢,獲取查詢結果填充數據框:
library(RODBC) cn <- odbcConnect("data source") df <- sqlQuery(cn,"TSQL Query") odbcClose(cn)
3,使用函數創建
第三種方法是通過函數 data.frame()創建數據框,用戶需要輸入指定的數據填充數據框變量,函數data.frame()的參數row.names用於指定行的標識符,有三種指定行標識符的方式:
- 設置行的名稱,為每一行命名,這樣,可以通過行名稱來索引觀測;
- 把該參數設置為NULL,取消行的命名,R引擎會自動生成遞增的整數序列作為行標識符,也就是所謂的行號;
- 也可以把行標識符設置為數據框的列名,這樣,R引擎把該列的值作為行標識符,這相當於關系表的主鍵列。
例如,以下腳本通過指定行名稱的方式來指定行標識符:
df <- data.frame( c1=letters[1:3], c2=c(1:3), c3=runif(3)>0.5, c4=c('r','g','b'), row.names=c('r1','r2','r3') )
打印數據框,數據框有兩個維度,行和列:
> df c1 c2 c3 c4 r1 a 1 TRUE r r2 b 2 FALSE g r3 c 3 FALSE b
二,查看數據框的元數據
數據框本身存儲列的名稱、行名稱、列數量、和行的數量等元數據。
1,查看列和行的名稱
通過函數colnames()或names()返回數據框的列名稱,通過函數rownames()返回數據框的行名稱,
> colnames(df) > names(df) [1] "c1" "c2" "c3" "c4" > rownames(df) [1] "r1" "r2" "r3"
2,查看行和列的數量
通過函數nrow()或函數ncol(),返回數據框的行數或列),函數length()返回的結果和ncol()函數返回的結果相同。
> nrow(df) [1] 3 > ncol(df) [1] 4
三,索引數據框
索引數據框,使用中括號[]和下標來訪問數據框,和索引向量一項,索引數據框的下標也有四種表示方式:正整數、負整數、邏輯值和名稱(行或列的名稱)。由於數據框是二維數據結構,有行和列,因此,下標的格式是[row,col], row是行下標,用於選擇行;col是列下標,用於選擇列。對於row和col,在索引數據框時,必須同時指定這兩個下標:
- 第一個下標用於選擇行,如果row是空白的,[ ,col] 表示選擇所有的行;
- 第二個下標用於選擇列,[row, ] 表示選擇所有列。
索引數據框,也可以設置邏輯向量為下標,而邏輯向量可以由向量的表達式來獲得,這使得數據框的索引較為復雜。不過,只要理解下標的四種表示方式,不過怎么組合,都不難掌握。
1,選擇多列
例如,獲得數據框的一個子集,索引數據框中的第一行和第二行,第二列和第三列的數據子集:
> df[1:2,2:3] c2 c3 r1 1 TRUE r2 2 FALSE
2,使用名稱來索引數據框
如果只選擇數據框的一列,可以使用:美元符號(&) + 列名稱 來選擇單列,在使用 下標和 [ ] 來選擇行。
例如,通過美元符號$和列名來索引數據框的列c1,通過下標和[]來選取第二行和第三行:
> df$c1[2:3] [1] b c Levels: a b c
從返回的結果中可以看到,R引擎把字符類型的列自動轉換為因子類型來存儲,可以使用as.character()函數把因子類型轉換為字符類型的向量:
> as.character(df$c1[2:3]) [1] "b" "c"
如果要引用單列的所有行,可以不對行進行過濾,使用 "&+ 列名", 返回該列的所有數據行,例如:
df$c1
使用這種方式索引數據框,得到的是向量,其行為和普通的向量相同,支持向量運算。
3,下標為邏輯向量
邏輯向量,通常是由向量的條件表達式計算得到的,例如:
> df$c2>1 [1] FALSE TRUE TRUE
查看邏輯向量的元素值,為TRUE的位置剛好是數據框c2列中大於1的行,因此,可以通過這種方式,按照特定的條件獲取數據框的子集,例如,獲取數據框中c2列大於1的數據行:
> df[df$c2>1, ] c1 c2 c3 c4 r2 b 2 FALSE g r3 c 3 TRUE b
當然,也可以使用邏輯運算符,組合多個條件,獲得滿足條件的所有數據行,例如:
df[df$c2>1 & df$c3, ]
4,小標為列名
當使用兩個中括號時,第一個中括號內指的是列名,包括所有數據行:
df['c1']
第二個中括號是行選擇器:
> df['c1'][df['c2']>1] [1] "b" "c"
舉個例子,第一個中括號索引c2列的所有的行,第二個中括號對行進行篩選,只選擇c2的值<=2的行:
df[,'c2'][df[,'c2']<=2]
四,獲取數據框的子集
從數據框中按照特定的條件獲取子集,這實際上是根據特定列的值,來限制返回的觀測的數量。
1,通過設置行索引獲取子集
這是利用數據框的下標為邏輯向量來過濾數據行,由於索引數據框,需要多次書寫數據框的名稱,df[df$c2<= df | c3, ] ,十分麻煩,為了簡化流程,可以使用函數with()或within(),這樣,可以省略數據框名稱和$符號,例如:
> with(df,df[c2<=2|c3,]) c1 c2 c3 c4 r1 a 1 FALSE r r2 b 2 TRUE g
2,通過subset()函數獲取子集
函數subset()用於獲取數據框的子集,第一個參數(x)是數據框;第二個參數(subset)是邏輯表達式,用於過濾數據行;第三個參數(select)是投影的數據列,用於選擇的特定的列。
subset(x, subset, select, drop = FALSE)
例如,從df中獲取c2不大於2,返回第二列和第三列的結果:
> subset(df,c2<=2,c(2:3)) c2 c3 r1 1 TRUE r2 2 FALSE
五,數據框的基本操作
操縱數據框,例如,選擇子集(subset),合並數據框,排序數據框,添加或修改數據列,把數據值排名等,最終把數據轉換成相應的形式,用於數據分析,本節只簡單分享操縱數據框的方法。
1,添加列和行
使用rbind()函數向數據框中添加一行或多行數據,也就是說,按行縱向擴展;使用cbind()函數向數據框中添加一列或多列數據,也就是說,按列橫向擴展。
2,合並數據框
使用merge9)函數合並數據框,merge()函數的作用類似於SQL語言中的連接(Join)操作,用於把兩個數據框,按照特定的數據列做連接操作,函數的定義如下:
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, suffixes = c(".x",".y"),...)
參數注釋:
- x,y 參數:指定合並的兩個數據框;
- by參數:字符串,指定合並列,當兩個數據框有相同的數據列名字時,merge函數將按照同名的數據列名稱合並;
- by.x,by.y 參數:字符串,分別指定數據框的合並列,用於指定merge函數將按照數據框x和y的哪些數據列進行合並;
- all:邏輯值,完全顯示兩個數據框的所有數據行,當合並列的值不存在於數據框x或y中,該數據框的列值顯示為NA;
- all.x,all.y:邏輯值,指定完全顯示的數據框,例如,當折merge函數的all.x=TRUE,all.y=FALSE是,合並的結果把數據框x的數據列全部顯示,如果合並列的值不存在於數據框y,那么y的其他數據列顯示為NA。
- sort:邏輯值,指定是否對結果排序;
- suffixes:為非合並列添加后綴;
例如,創建兩個數據框,按照df1的數據列x,和數據框df2的數據列m,對這兩個數據框執行合並操作:
> df1=data.frame(x=c('a','c','e'),y=1:3) > df2=data.frame(m=c('a','c','f'),n=4:6) > merge(df1,df2,by.x='x',by.y='m') x y n 1 a 1 4 2 c 2 5 > > merge(df1,df2,by.x='x',by.y='m',all=TRUE) x y n 1 a 1 4 2 c 2 5 3 e 3 NA 4 f NA 6
2,添加和替換列
方法1:直接對數據框的數據列進行賦值,來實現對數據框的數據列的添加或替換:
df1[,'z'] <- c('z1','z2','z3') df1$z <- c('z1','z2','z3')
方法2:使用with參數,with函數(with(data, expr))接受一個數據框對象和要計算的表達式作為輸入參數,with函數返回值是表達式的值,with函數只能添加或修改一個數據列:
df1 <- with(df1,{z=c('z1','z2','z3')})
方法3:使用within函數,within函數(within(data, expr))接受一個數據框對象和要計算的表達式作為輸入參數,within函數返回的是更新后的數據框對象,within函數可以在大括號中添加多個表達式,能夠一次操作多個數據列:
df1 <- within(df1,{z=c('z1','z2','z3')} )
方法4:使用plyr包中的mutate函數,該函數用於向數據框中添加數據列或轉換已經存在的數據列,接受一個數據框對象,和多個”name=value“對,返回修改后的數據框對象:
df1 <- df1 %>% mutate(z=c('z1','z2','z3'))
3,排序
order()函數能夠對數據框進行排序,order(x)函數:返回第i個元素是x中元素在排序之后的序號,對數據框進行排序時,可以分兩步進行下去,第一步獲取行的序號,第二部按照行號查詢數據框:
> y_order <- order(df1[,'y']) > df1[y_order,]
還有一個方法,使用dplyr包中的arrange函數,只用一行就能實現對數據框的排序:
arrange(df1,y)
4,排名
rank()函數可以為數據框中的列進行排名,不過rank()函數只能作用於向量,只能返回向量元素的排名:
rank(x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"))
操作數據框,在數據分析中占用很大的比重,后續,我們再深入探討。