[R Lang] R Lang與高級醫學統計學(4)
Adrian Chen

這篇文章講R Lang中資料的輸入和輸出。R Lang是一個統計導向型的程式設計語言,目的是統計和處理大量的複雜資料。因此在很多時候,R Lang都將會被用來處理大型資料。對於真正的大型資料,我們通常是在資料庫軟體中或者是試算表軟體中存儲好外部檔案,然後再讓R Lang從外部檔案讀入進行處理。

資料框架

事實上,上一篇文章中有講到一種特殊的列表格式叫做資料框架(data frame)。我們說它就像是一個二維度表格一樣。因此,外部輸入的資料通常儲存在data frame的物件中。

舉一個例子,這是一份臨床試驗結果:

No age sex DM DMyr preAC prePC postAC postPC Med SIDE PREKS
1 670 0 0 10 120 160 140 180 0 0 56
2 67 0 0 11 100 150 150 220 0 1 62
3 72 1 0 4 150 200 120 150 2 0 60
4 82 1 0 8 150 200 160 250 0 1 47
5 73 1 0 3 85 110 140 200 0 0 44

我們先來看一下資料框架有什麼特徵:

  • 第1列(橫列,row),可以是變數的變數名(variable names)
  • 第1列(row),有時是變數的欄位標籤(column label),而第2列(row)為變數名
  • 每個變數各自形成1欄(縱行, column)
  • 第1欄(縱行, column)為個體辨識碼(label, identification),或稱 列位標籤(row label)
  • 每一欄(變數)的變數值形式可以是實數,文字,邏輯變數
  • 第一欄(column)有時候是列位標籤 (row label)
  • 變數名稱以英文為起始,之後可包含文字與數字,不可使用標點符號與空格。
  • 變數值通常為數字,整數或文字,儘量避免直接輸入文字,因為大小寫,符號,空格的輸入經常造成錯誤
  • 若原始資料沒有變數名或標籤,R Lang讀入資料時可以同時輸入變數名,或讀入資料後,再輸入變數名

輸入外部ASCII資料檔

資料之間以空格分隔的資料檔

純文字的ASCII檔若以空格分開,則通常的副檔名為.dat或.prn或.txt。這類檔案通常直接由資料庫處理軟體輸出。

使用read.table()函式來進行讀取。該函式的定義如下:

1
2
3
4
5
6
7
8
9
10
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:需要R Lang讀取的自帶分隔符的ASCII檔案。絕對路徑或是相對於工作空間的相對路徑。
  • header:logical引數。表示檔案的第一列是否含有變數名。如果為TRUE,要求第一列的欄數比資料列的數量少一欄。
  • sep:分隔元。預設為"",表示一個或多個空格、tab、換行字元或迴車。
  • quote:特殊字元的字串劃定接線的字串。預設為"或單引號'
  • dec:資料中表示小數點的字元。預設為.
  • numerals:字串類型。用於指定文件中的數字轉換為雙精度資料時丟失精度的情況下如何進行轉換。
  • row.names:儲存列名的向量。可以使用此參數以向量的形式給出每列的實際列名。 或要讀取的表中包含列名稱的行序號或行名字串。在資料檔案中有列頭且首列的欄位名稱比資料欄少一個的情況下,資料檔案中第1欄將被視為欄位名稱。除此情況外,在沒有給定該參數時,讀取的列名將會自動編號。可以使用row.names = NULL強制列進行編號。
  • col.names:指定欄名的向量。缺省時使用V+序號構成。
  • as.is:此引數用於確定read.table()函式讀取字元型資料時是否轉換為因子型變數。當其取值為FALSE時,此函式將把字元型資料轉換為因子型資料,取值為TRUE時,仍將其保留為字元型。其取值可以是邏輯值向量(必要時可以循環賦值),數值型向量或字元型向量,以控制哪些列不會轉換為因子。
  • na.strings:可選的用於表示缺失值的字元向量。
  • colClasses:用於指定列所屬類別的字串向量。
  • nrows:整數型數。用於指定從檔案讀取的最大行數。負數或其它無效值將會被忽略。
  • skip:整數型數。讀取資料時忽略的行數。
  • check.names:邏輯值。此引數值設定為TRUE時,資料框中的變數名稱將會被檢查,以確保符在語法上是有效的變數名稱。
  • blank.lines.skip:邏輯值,此參數值設定為TRUE時,資料檔中的空白列將被忽略。預設值為TRUE。
  • fill:邏輯值。在沒有忽略空白行的情況下(即blank.lines.skip=FLASE),且fill設定為TRUE時,如果資料檔案中某列的資料少於其他列,則自動新增空白域。
  • strip.white:邏輯值,預設為FALSE。此引數只在指定了sep因素時才有效。當此引數設定為TRUE時,資料檔案中沒有包圍的字串域的前邊和後邊的空格將會被去掉。
  • comment.char:字元型。包含單一字元或空字元的向量。代表註解字元的開始字元。可以使用””關閉註解。
  • allowEscapes:邏輯值。類似“\n”這種C風格的轉義符。如果這種轉義符並不是包含在字串中,則函式可能會解釋為欄位分隔符號。
  • flush:邏輯值。預設值為FALSE。 當此引數值設定為TRUE時,則函數讀取完指定列數後將轉到下一行。這允許用戶在最後一個字段後面添加註釋。
  • stringAsFactors:邏輯值,標記處字元向量是否需要轉換為因子,預設是TRUE。
  • fileEncoding:字串類型,指定檔案的編碼方式。如果指定了該引數,則文字資料會依照指定的格式重新編碼。
  • encoding:假定輸入字串的編碼方式。
  • text:字串類型。當未提供file引數時,則函式可以透過一個文字連結從text讀取資料。
  • skipNul:邏輯值。是否忽略空值。 預設為FALSE。

大部分的引數保持預設值就好。我們來看一個例子:

1
2
3
4
5
6
7
8
9
File <- read.table(
file = "./file.txt",
sep = " ", # 設定由一個空格分隔
quote = "\"'", # 設定quote為單引號或雙引號
dec = ".", # 設定小數點字元為.
row.names = NULL, # 強制列編號
as.is = TRUE, # 自動將字元型轉化為因子型
na.strings = c("", ".", "NA") # 缺省值
)

資料之間以逗號分隔的資料檔

對於逗號分隔的資料檔,其副檔名通常為.csv。在讀取的時候我們依然可以使用read.table()函式,透過設定sep引數為逗號來進行讀取。另一種方法是透過read.csv()函式來讀取。該函式預設將分隔符設定成逗號。

載入和讀取R Lang內建資料框架和貢獻套件中的資料框架

R Lang出於規範和示例的原因,已經為我們內建了許多資料框架。我們可以使用這些內建的資料框架來練習R Lang的作業。

可以使用data()函式來查看R Lang的內置資料框架。使用head()函式來查看資料框架的內容。

1
2
3
4
5
6
7
8
9
10
11
12
## 查看所有的R Lang內置資料框架列表
data()

## 查看資料框架Orange的內容
head(Orange)
## Tree age circumference
## 1 1 118 30
## 2 1 484 58
## 3 1 664 87
## 4 1 1004 115
## 5 1 1231 120
## 6 1 1372 142

這兩個函式還有其他的作用。在其他貢獻套件中同樣有其內建的資料框架。使用data()函式就可以將這些資料框架載入,而使用head()函式可以讀取這些資料框架的內容。例如我們想要讀取MASS套件中的VA框架:

1
2
3
library(MASS) # 載入MASS
data(VA, package = "MASS") # 載入MASS套件中的VA資料框架
head(VA) # 讀取VA資料框架

請注意,在R Lang的內建資料框架中,不需要data()載入即可使用head()讀取。而貢獻套件中的資料框架必須先載入,才能讀取。因為R Lang預設情況下不會認識這些貢獻的資料框架。

輸出R Lang資料

使用write.table()write.csv()函式將R Lang的資料匯出到外部資料檔案。它們的引數如下:

  • x = 匯出的R Lang物件名
  • file = 路徑與檔案名稱
  • append = FALSE 預設不在檔案末端附加資料
  • quote = “\”” 預設文字變數值使用雙引號將
  • sep = “ “ 預設空白分隔符號
  • eol = “\n” 設定換行符號
  • na = NA 設定 NA 符號
  • dec = ‘.’ 設定小數點符號
  • row.names = TRUE 設定輸出 row names
  • col.names = TRUE 設定輸出變數名(column names)
  • qmethod = c(“escape”, “double”) 文字變數值有當引號時的分隔符號
  • fileEncoding = “” 設定檔案編碼

輸出Rds格式的資料

對於大型資料集,如果存入普通的我外部資料檔中,每次讀取將耗費大量時間。而如果將R Lang中的data frame物件直接儲存成Rds格式,讀取就會快很多。

使用saveRDS()readRDS()兩個函式來進行這個作業。

1
2
3
4
x <- c(1:5)
saveRDS(x, file = "./x.Rds")

new_x <- readRDS(file = "./x.Rds")