R 簡介

這是 R(「GNU S」)的簡介,R 是一種用於統計運算和繪圖的語言和環境。R 類似於獲獎的1 S 系統,該系統是由約翰·錢伯斯等人於貝爾實驗室開發。它提供了各種統計和繪圖技術(線性和非線性建模、統計檢定、時間序列分析、分類、聚類,...)。

本手冊提供有關資料類型、程式設計元素、統計建模和繪圖的資訊。

本手冊適用於 R 4.3.3 版(2024-02-29)。

版權所有 © 1990 W. N. Venables
版權所有 © 1992 W. N. Venables & D. M. Smith
版權所有 © 1997 R. Gentleman & R. Ihaka
版權所有 © 1997, 1998 M. Maechler
版權所有 © 1999–2023 R Core Team

在所有副本上保留版權公告和此許可公告,則允許製作和分發此手冊的逐字副本。

在逐字複製的條件下,允許複製和分發此手冊的修改版本,但前提是整個衍生作品的發布都符合與本許可公告相同的許可公告條款。

在上述修改版本條件下,允許複製和分發此手冊的翻譯版本,但此許可公告可以陳述為 R Core Team 批准的翻譯。

目錄


這份 R 簡介源自於比爾·維納布爾斯和大衛·M·史密斯在 1990-2 年於阿德雷德大學撰寫的一組原始筆記,說明 S 和 S-PLUS 環境。我們做了一些小變更,以反映 R 和 S 程式之間的差異,並擴充了一些內容。

我們要對比爾·韋納布爾斯(和戴維·史密斯)表示衷心的感謝,感謝他們允許我們以這種方式分發筆記的修改版本,並感謝他們一直以來對 R 的支持。

我們隨時歡迎意見和更正。請將電子郵件寄至

給讀者的建議

大多數 R 新手會從附錄 A 中的入門課程開始。這應該能讓讀者熟悉 R 課程的風格,更重要的是能立即回饋實際發生的事情。

許多使用者會使用 R 主要都是因為它的圖形功能。請參閱 圖形程序,幾乎可以在任何時候閱讀,不必等到消化完所有前一章節。


1 簡介和預備知識


1.1 R 環境

R 是一套整合的軟體工具,用於資料處理、計算和圖形顯示。在其他功能中,它具有

  • 有效率的資料處理和儲存功能,
  • 一組用於計算陣列(特別是矩陣)的運算子,
  • 一個龐大、一致、整合的資料分析中間工具集合,
  • 用於資料分析和顯示的圖形功能,可直接在電腦上或列印成實體,以及
  • 一個開發完善、簡單且有效率的程式語言(稱為「S」),其中包括條件式、迴圈、使用者定義的遞迴函數和輸入輸出功能。(事實上,系統提供的函數大多數都是用 S 語言編寫的。)

「環境」一詞用於將其描述為一個經過完整規劃且一致的系統,而不是像其他資料分析軟體常見的情況那樣,逐漸累積非常具體且不靈活的工具。

R 是互動式資料分析新開發方法的載體。它發展迅速,並已透過大量 套件 進行擴充。然而,大多數用 R 編寫的程式本質上都是暫時的,只針對單一資料分析撰寫。


1.3 R 和統計

我們對 R 環境的介紹並未提及統計,但許多人將 R 用作統計系統。我們比較喜歡將它視為一個環境,其中已實作許多古典和現代統計技術。其中一些技術已內建於 R 基本環境中,但許多技術則以套件的形式提供。R 提供了大約 25 個套件(稱為「標準」和「建議」套件),且透過 CRAN 系列的網際網路網站(透過 https://CRAN.R-project.org)和其他地方,還可以取得更多套件。稍後會提供有關套件的更多詳細資訊(請參閱 套件)。

大多數古典統計和許多最新方法都可搭配 R 使用,但使用者可能需要做好一點準備工作才能找到這些方法。

S(因此也包括 R)與其他主要統計系統在哲學上存在著一個重要的差異。在 S 中,統計分析通常分為一系列步驟執行,且中間結果會儲存在物件中。因此,SAS 和 SPSS 會提供回歸或判別分析的大量輸出,而 R 會提供最少的輸出,並將結果儲存在適合物件中,以便進一步的 R 函數進行查詢。


1.4 R 和視窗系統

使用 R 最方便的方法是在執行視窗系統的圖形工作站上。本指南針對擁有此設施的使用者。特別是,我們偶爾會提到在 X 視窗系統上使用 R,儘管所述內容的大部分通常適用於 R 環境的任何實作。

大多數使用者會發現有必要不時與電腦上的作業系統直接互動。在本指南中,我們主要討論與 UNIX 電腦上作業系統的互動。如果您在 Windows 或 macOS 上執行 R,您需要做一些小調整。

設定工作站以充分利用 R 的可自訂功能是一個直接但有點繁瑣的程序,在此不進一步探討。有困難的使用者應尋求當地專家協助。


1.5 互動式使用 R

當您使用 R 程式時,它會在需要輸入指令時發出提示。預設提示為「>」,在 UNIX 上可能與 shell 提示相同,因此可能看起來沒有任何動作。然而,正如我們將看到的,如果您願意,可以輕鬆變更為不同的 R 提示。我們假設 UNIX shell 提示為「$」。

在 UNIX 下使用 R 時,建議初次使用程序如下

  1. 建立一個獨立的子目錄,例如 work,來儲存您將使用 R 處理此問題的資料檔案。當您使用 R 處理此特定問題時,這將成為工作目錄。
    $ mkdir work
    $ cd work
    
  2. 使用指令啟動 R 程式
    $ R
    
  3. 此時可以發出 R 指令(請參閱後續說明)。
  4. 若要退出 R 程式,請使用指令
    > q()
    

    此時系統會詢問您是否要儲存 R 工作階段的資料。在某些系統中,這將開啟一個對話方塊,而在其他系統中,您會收到一個文字提示,您可以回應 yesnocancel(單一字母縮寫即可)來在退出前儲存資料、不儲存就退出或返回 R 工作階段。已儲存的資料將可在未來的 R 工作階段中使用。

後續的 R 工作階段很簡單。

  1. work 設為工作目錄,並像之前一樣啟動程式
    $ cd work
    $ R
    
  2. 使用 R 程式,並在工作階段結束時以 q() 指令終止。

若要在 Windows 下使用 R,遵循的程序基本上相同。建立一個資料夾作為工作目錄,並在 R 捷徑的 開始於 欄位中設定該資料夾。然後,按兩下圖示啟動 R。

1.6 簡介工作階段

強烈建議希望在繼續之前在電腦上體驗 R 的讀者完成 範例工作階段 中提供的簡介工作階段。


1.7 取得函數與功能的說明

R 內建的說明功能類似於 UNIX 的 man 功能。若要取得任何特定函數的詳細資訊,例如 solve,指令如下:

> help(solve)

另一種方法為:

> ?solve

對於由特殊字元指定的函數,引數必須置於雙引號或單引號中,使其成為「字串」:這也適用於少數具有語法意義的字詞,包括 ifforfunction

> help("[[")

兩種引號都可以用來跳脫另一種引號,例如字串 "It's important"。我們的慣例是優先使用雙引號。

在大部分的 R 安裝中,說明文件都以 HTML 格式提供,執行下列指令即可開啟:

> help.start()

這會開啟一個網頁瀏覽器,讓你可以透過超連結瀏覽說明頁面。在 UNIX 中,後續的說明請求會傳送到以 HTML 為基礎的說明系統。由 help.start() 載入的頁面中的「搜尋引擎與關鍵字」連結特別有用,因為它包含一個高階概念清單,可以搜尋現有的函數。這是一個快速了解 R 所提供功能廣度的絕佳方法。

你可以使用 help.search 指令(或 ??)以各種方式搜尋說明。例如:

> ??solve

嘗試 ?help.search 以取得詳細資料和更多範例。

通常可以透過執行來執行說明主題中的範例

> example(topic)

R 的 Windows 版本有其他選用的說明系統:請使用

> ?help

以取得更多詳細資料。


1.8 R 指令、大小寫敏感等。

技術上來說,R 是一種運算式語言,語法非常簡單。它大小寫敏感,就像大多數基於 UNIX 的套件一樣,因此 Aa 是不同的符號,會指涉不同的變數。可以在 R 名稱中使用的符號組會依據執行 R 的作業系統和國家/地區而有所不同(技術上來說,會依據使用的地區設定而有所不同)。通常允許使用所有字母數字符號2(在某些國家/地區中,這包括重音字母)加上「.」和「_」,但限制為名稱必須以「.」或字母開頭,如果以「.」開頭,第二個字元不能是數字。名稱的長度基本上沒有限制。

基本指令包含 表達式指定。如果表達式作為指令提供,它會被評估、列印(除非特別設定為不可見),且值會遺失。指定也會評估表達式並將值傳遞給變數,但結果不會自動列印。

指令會以分號(‘;’)或換行符號分隔。基本指令可以使用大括號(‘{’ 和 ‘}’)群組成一個複合表達式。幾乎3可以在任何地方放置 註解,從井號(‘#’)開始,該行結尾的所有內容都是註解。

如果指令在行尾尚未完成,R 會提供不同的提示,預設為

+

在第二行和後續行,並繼續讀取輸入,直到指令在語法上完成。使用者可以變更此提示。我們通常會省略延續提示,並透過簡單縮排來表示延續。

在主控台中輸入的指令行受限4於約 4095 位元組(非字元)。


1.9 喚回及修正先前的指令

在許多版本的 UNIX 和 Windows 上,R 提供了一種機制來喚回並重新執行先前的指令。鍵盤上的垂直箭頭鍵可用於在指令歷程中向前和向後捲動。一旦以這種方式找到指令,就可以使用水平箭頭鍵在指令中移動游標,並可以使用DEL鍵移除字元或使用其他鍵新增字元。稍後會提供更多詳細資訊:請參閱指令列編輯器

UNIX 下的喚回和編輯功能高度可自訂。您可以透過閱讀readline函式庫的手冊條目來瞭解如何執行此操作。

或者,Emacs 文字編輯器透過ESSEmacs Speaks Statistics)提供更通用的支援機制,以與 R 互動式地工作。請參閱R 統計系統常見問答集中的R 和 Emacs


1.10 從檔案執行指令或將輸出導向檔案

如果指令5儲存在外部檔案中,例如工作目錄work中的commands.R,則可以使用指令在 R 會話中隨時執行這些指令

> source("commands.R")

對於 Windows,來源也會顯示在 檔案功能表中。函數 sink

> sink("record.lis")

會將所有後續的輸出從主控台轉移到外部檔案 record.lis。指令

> sink()

會將其還原到主控台上。


1.11 資料永久性和移除物件

R 建立和處理的實體稱為 物件。這些可能是變數、數字陣列、字元字串、函數或由這些元件建置的更通用的結構。

在 R 執行階段中,物件會以名稱建立並儲存 (我們會在下一個區段討論這個程序)。R 指令

> objects()

(或者 ls()) 可用於顯示目前儲存在 R 中 (大部分) 物件的名稱。目前儲存的物件集合稱為 工作區

若要移除物件,可以使用函數 rm

> rm(x, y, z, ink, junk, temp, foo, bar)

在 R 執行階段中建立的所有物件都可以永久儲存在檔案中,以供將來的 R 執行階段使用。在每個 R 執行階段結束時,您都有機會儲存所有目前可用的物件。如果您表示要執行此動作,物件會寫入目前目錄中稱為 .RData6 的檔案,而執行階段中使用的指令列會儲存到稱為 .Rhistory 的檔案中。

當 R 從同一個目錄在較晚的時間啟動時,它會從這個檔案重新載入工作空間。同時,也會重新載入相關的指令記錄。

建議您應為使用 R 進行的分析使用個別的工作目錄。在分析過程中,通常會建立名稱為 xy 的物件。此類名稱在單一分析的脈絡中通常有意義,但若在同一個目錄中進行多個分析,則很難決定它們可能的名稱。


2 簡單的操作;數字和向量


2.1 向量和指定

R 運作於已命名的資料結構。最簡單的此類結構是數值的向量,它是一個由數字的有序集合組成的單一實體。若要設定一個名為 x 的向量,例如,包含五個數字,即 10.4、5.6、3.1、6.4 和 21.7,請使用 R 指令

> x <- c(10.4, 5.6, 3.1, 6.4, 21.7)

這是一個指定陳述,使用函數 c(),在這個脈絡中,它可以採用任意數量的向量引數,其值是一個向量,方法是將其引數從頭到尾串接起來。7

在表達式中單獨出現的數字會被視為長度為一的向量。

請注意,賦值運算子(「<-」),由兩個字元「<」(「小於」)和「-」(「減號」)嚴格並排組成,且它「指向」接收表達式值的物件。在大部分的語境中,運算子「=」可以用作替代方案。

也可以使用函數 assign() 進行賦值。與上述相同的賦值,可以用以下方式進行等效處理:

> assign("x", c(10.4, 5.6, 3.1, 6.4, 21.7))

通常的運算子 <- 可以視為此語法的捷徑。

也可以使用賦值運算子的明顯變更,朝其他方向進行賦值。因此,可以使用以下方式進行相同的賦值:

> c(10.4, 5.6, 3.1, 6.4, 21.7) -> x

如果表達式用作完整的指令,則會列印值且遺失8。因此,如果我們現在要使用指令

> 1/x

則會在終端機列印五個值的倒數(當然,x 的值不變)。

進一步的賦值

> y <- c(x, 0, x)

會建立一個向量 y,其中包含 11 個項目,由兩個 x 副本組成,中間有一個零。


2.2 向量運算

向量可以用在運算式中,運算會逐元素執行。出現在同一個運算式中的向量長度不一定要相同。如果長度不同,運算式的值會是一個向量,長度和運算式中出現的最長向量相同。運算式中較短的向量會被重複使用,直到長度與最長向量相符為止(可能會有小數位)。特別地,常數會被重複。因此,使用上述的指定,指令

> v <- 2*x + y + 1

會產生一個新的向量 v,長度為 11,建構方式為逐元素相加:2*x 重複 2.2 次、y 重複一次,以及 1 重複 11 次。

基本算術運算子為常見的 +-*/^(用於乘方)。 此外,所有常見的算術函數皆可使用。logexpsincostansqrt 等函數皆具有其慣用意義。 maxmin 分別選取向量中最大和最小的元素。 range 函數的值為長度為 2 的向量,即 c(min(x), max(x)) length(x)x 中的元素數量, sum(x) 提供 x 中元素的總和,prod(x) 則提供其乘積。

兩個統計函數為 mean(x),用於計算樣本平均數,等於 sum(x)/length(x) 以及 var(x),用於提供

sum((x-mean(x))^2)/(length(x)-1)

或樣本變異數。如果 var() 的參數為 n 乘以 p 的矩陣,則值為 p 乘以 p 的樣本共變異數矩陣,其將列視為獨立的 p 元樣本向量。

sort(x) 傳回一個向量,大小與 x 相同,元素以遞增順序排列;不過有其他更彈性的排序工具可用(請參閱 order()sort.list(),它們會產生一個用於排序的排列)。

請注意,maxmin 會選取其引數中最大和最小的值,即使提供多個向量。平行最大值和最小值函數 pmaxpmin 會傳回一個向量(長度等於其最長引數),每個元素包含任何輸入向量中該位置的最大(最小)元素。

在多數情況下,使用者不會在意數字向量中的「數字」是整數、實數,甚至複數。內部計算是以雙精度實數或雙精度複數進行,如果輸入資料是複數。

若要處理複數,請提供明確的複數部分。因此

sqrt(-17)

會產生 NaN 和警告,但

sqrt(-17+0i)

會將運算結果視為複數。


2.3 產生規則序列

R 有許多用於產生常用數字序列的工具。例如 1:30 是向量 c(1, 2, …, 29, 30) 冒號運算子在表達式中具有高優先權,因此,例如 2*1:15 是向量 c(2, 4, …, 28, 30)。將 n <- 10 放入並比較序列 1:n-11:(n-1)

結構 30:1 可用於向後產生序列。

函數 seq() 是用於產生序列的更通用的工具。它有五個參數,其中只有部分參數可以在任何一個呼叫中指定。如果給出前兩個參數,則指定序列的開始和結束,如果這兩個參數是給出的唯一兩個參數,則結果與冒號運算子相同。也就是說 seq(2,10) 與向量 2:10 相同。

傳遞給 seq() 的參數,以及許多其他 R 函數的參數,也可以以命名形式給出,這種情況下它們出現的順序無關緊要。前兩個參數可以命名為 from=to=;因此 seq(1,30)seq(from=1, to=30)seq(to=30, from=1) 都與 1:30 相同。傳遞給 seq() 的後兩個參數可以命名為 by=length=,分別指定序列的步長和長度。如果沒有給出這些參數,則假設預設 by=1

例如

> seq(-5, 5, by=.2) -> s3

s3 中產生向量 c(-5.0, -4.8, -4.6, …, 4.6, 4.8, 5.0)。類似地

> s4 <- seq(length=51, from=-5, by=.2)

s4 中產生相同的向量。

第五個參數可以命名為 along=vector,通常用作建立序列 1, 2, …, length(vector) 的唯一參數,或是在向量為空時建立空序列(因為向量可以為空)。

相關函數為 rep() ,可以用於以各種複雜方式複製物件。最簡單的形式為

> s5 <- rep(x, times=5)

這會將 x 的五個拷貝從頭到尾放入 s5 中。另一個有用的版本為

> s6 <- rep(x, each=5)

這會在移到下一個元素之前,先重複 x 的每個元素五次。


2.4 邏輯向量

除了數值向量,R 也允許操作邏輯量。邏輯向量的元素可以有值 TRUEFALSENA(表示「不可用」,見下文)。前兩個通常分別簡寫為 TF。但請注意,TF 只是預設設定為 TRUEFALSE 的變數,但不是保留字,因此使用者可以覆寫。因此,您應該始終使用 TRUEFALSE

邏輯向量是由 條件 產生的。例如

> temp <- x > 13

temp 設定為與 x 長度相同的向量,其中 FALSE 值對應於 x 中未滿足條件的元素,而 TRUE 值對應於滿足條件的元素。

邏輯運算子為 <<=>>===(表示完全相等)和 !=(表示不相等)。 此外,如果 c1c2 是邏輯表達式,則 c1 & c2 是它們的交集(「且」),c1 | c2 是它們的聯集(「或」),而 !c1c1 的否定。

邏輯向量可以用於一般算術中,在這種情況下,它們會轉換為數字向量,FALSE 會變成 0TRUE 會變成 1。但是,在某些情況下,邏輯向量及其轉換後的數字對應項並不等效,例如,請參閱下一個小節。


2.5 遺失值

在某些情況下,向量的組成部分可能並非完全已知。當一個元素或值在統計意義上「不可用」或為「遺失值」時,向量中可能會保留一個位置,方法是將特殊值 NA 指定給它。 一般而言,對 NA 執行的任何操作都會變成 NA。這項規則的動機很簡單,如果操作的說明不完整,則無法得知結果,因此不可用。

函數 is.na(x) 會產生一個邏輯向量,其大小與 x 相同,如果且僅當 x 中對應的元素為 NA 時,其值為 TRUE

> z <- c(1:3,NA);  ind <- is.na(z)

請注意,邏輯表達式 x == NAis.na(x) 有很大的不同,因為 NA 並非真正的值,而是表示不可用數量的標記。因此,x == NA 是與 x 長度相同的向量,其所有值均為 NA,因為邏輯表達式本身不完整,因此無法判定。

請注意,數值計算會產生第二種類型的「遺失」值,即所謂的非數字NaN值。範例為

> 0/0

> Inf - Inf

兩者皆會產生 NaN,因為無法合理定義結果。

總之,is.na(xx)NANaN兩者皆為 TRUE。若要區分這些值,is.nan(xx) 僅對 NaNTRUE

有時在未加引號列印字元向量時,遺失值會列印為 <NA>


2.6 字元向量

在 R 中,經常使用字元量和字元向量,例如作為繪圖標籤。在需要時,它們會以雙引號字元分隔的字元序列表示,例如 "x-values""New iteration results"

字元字串使用相符的雙 (") 或單 (') 引號輸入,但使用雙引號 (或有時不加引號) 列印。它們使用 C 風格的跳脫序列,使用 \ 作為跳脫字元,因此 \ 會輸入並列印為 \\,而在雙引號內 " 會輸入為 \"。其他有用的跳脫序列為 \n (換行)、\t (定位標籤) 和 \b (退格鍵);請參閱 ?Quotes 取得完整清單。

字元向量可透過 c() 函數串接成一個向量;其使用範例會經常出現。

paste() 函數會接收任意數量的引數,並將它們一個一個串接成字串。引數中給定的任何數字都會以明顯的方式強制轉換成字串,也就是說,它們會像列印時那樣轉換。預設情況下,引數在結果中會以一個空白字元分隔,但這可以用命名引數 sep=字串 來變更,將其變更為 字串,甚至可以是空的。

例如

> labs <- paste(c("X","Y"), 1:10, sep="")

labs 變成字元向量

c("X1", "Y2", "X3", "Y4", "X5", "Y6", "X7", "Y8", "X9", "Y10")

特別注意,這裡也會對短清單進行循環利用;因此, c("X", "Y") 會重複 5 次以符合序列 1:109


2.7 索引向量;選取和修改資料集的子集

可以透過在向量名稱後加上方括號中的索引向量來選取向量的元素子集。更一般來說,任何評估為向量的表達式都可以透過在表達式後立即加上方括號中的索引向量來選取其元素的子集。

此類索引向量可以是四種不同類型之一。

  1. 邏輯向量。在此情況下,索引向量會循環利用為與要選取元素的向量相同的長度。索引向量中對應於 TRUE 的值會選取,而對應於 FALSE 的值會略過。例如
    > y <- x[!is.na(x)]
    

    建立(或重新建立)一個物件 y,它將包含 x 的非遺失值,順序相同。請注意,如果 x 有遺失值,y 將會比 x 短。另外

    > (x+1)[(!is.na(x)) & x>0] -> z
    

    建立一個物件 z,並將向量 x+1 的值放入其中,其中 x 中對應的值既非遺失值,且為正值。

  2. 一個正整數量的向量。在這種情況下,索引向量中的值必須位於集合 {1, 2, …, length(x)} 中。向量的對應元素會被選取並串接,依據該順序,在結果中。索引向量可以是任何長度,而結果與索引向量長度相同。例如 x[6]x 的第六個組成,而
    > x[1:10]
    

    選取 x 的前 10 個元素(假設 length(x) 不小於 10)。另外

    > c("x","y")[rep(c(1,2,2,1), times=4)]
    

    (這是一個不太可能做的事)產生一個長度為 16 的字元向量,包含 "x", "y", "y", "x" 重複四次。

  3. 一個負整數量的向量。此類索引向量指定要排除而非包含的值。因此
    > y <- x[-(1:5)]
    

    給予 y 所有元素,除了 x 的前五個元素。

  4. 字元字串的向量。此可能性僅適用於物件具有 names 屬性來識別其組件的情況。在此情況下,名稱向量的子向量可以用與上面第 2 項中的正整數標籤相同的方式使用。
    > fruit <- c(5, 10, 1, 20)
    > names(fruit) <- c("orange", "banana", "apple", "peach")
    > lunch <- fruit[c("apple","orange")]
    

    優點是字母數字 名稱 通常比 數字索引 更容易記住。此選項與資料框搭配使用時特別有用,我們稍後會看到。

索引式表達式也可以出現在接收端指派中,在這種情況下,指派操作僅執行於 向量的那些元素。表達式必須為 vector[index_vector] 形式,因為在向量名稱中放置任意表達式在此處沒有太大意義。

例如

> x[is.na(x)] <- 0

用零取代 x 中的任何遺失值,且

> y[y < 0] <- -y[y < 0]

效果與

> y <- abs(y)

2.8 其他類型的物件

向量是 R 中最重要的物件類型,但還有其他幾種類型,我們將在後面的章節中更正式地介紹。

  • 矩陣 或更廣義的 陣列 是向量的多維概括。事實上,它們 可以由兩個或更多索引編址並將以特殊方式列印的向量。請參閱 陣列和矩陣
  • 因子 提供處理分類資料的簡潔方式。請參閱 已排序和未排序因子
  • 清單是向量的通用形式,其中各個元素不必是同種類型,而且它們本身通常是向量或清單。清單提供一個便利的方式來傳回統計運算的結果。請參閱 清單
  • 資料框是類似矩陣的結構,其中各欄可以是不同類型。將資料框視為「資料矩陣」,每一個觀察單位有一列,但(可能)同時包含數值和類別變數。許多實驗最適合用資料框來描述:處理是類別的,但反應是數值的。請參閱 資料框
  • 函數本身是 R 中的物件,可以儲存在專案的工作區中。這提供一個簡單且便利的方式來擴充 R。請參閱 撰寫您自己的函數

3 物件、它們的模式和屬性


3.1 內在屬性:模式和長度

R 運算的實體在技術上稱為物件。範例包括數值(實數)或複數值的向量、邏輯值的向量和字元字串的向量。這些稱為「原子」結構,因為它們的組成部分都是同種類型或模式,即數值10複數邏輯字元原始

向量的值必須全部具有相同的模式。因此,任何給定的向量都必須明確地是邏輯數值複數字元原始。(這個規則唯一明顯的例外是列為NA的特殊「值」,表示無法取得的數量,但事實上有好幾種NA的類型。)請注意,一個向量可以是空的,但仍然具有模式。例如,空的字元字串向量列為character(0),而空的數值向量列為numeric(0)

R 也會對稱為串列的物件進行運算,模式為串列。這些是物件的有序序列,個別物件可以是任何模式。串列稱為「遞迴」而非原子結構,因為它們的組成部分本身也可以是串列。

其他遞迴結構是模式為函數表達式的結構。函數是構成 R 系統一部分的物件,以及類似的使用者撰寫函數,我們稍後會詳細討論。表達式作為物件構成 R 的進階部分,除了在討論 R 中用於建模的公式時會間接討論到之外,本指南不會討論。

我們所謂物件的模式是指其基本組成單位的基本類型。這是物件「屬性」的一種特殊情況。每個物件的另一個屬性是其長度。函式 mode(object)length(object) 可用於找出任何已定義結構的模式和長度 11

物件的進一步屬性通常由 attributes(object) 提供,請參閱 取得和設定屬性。基於此,模式長度也稱為物件的「內在屬性」。

例如,如果 z 是長度為 100 的複數向量,則在表達式 mode(z) 中,字元字串為 "complex",而 length(z)100

R 幾乎在任何可以合理考慮的地方都能應付模式的變更(以及一些可能無法應付的地方)。例如,使用

> z <- 0:9

我們可以放入

> digits <- as.character(z)

之後,digits 為字元向量 c("0", "1", "2", …, "9")。進一步的強制轉換或模式變更會再次重建數值向量

> d <- as.integer(digits)

現在 dz 相同。12 有大量的 as.something() 形式的函式,可用於從一種模式強制轉換為另一種模式,或用於賦予物件它可能尚未具備的其他一些屬性。讀者應參閱不同的說明檔案以熟悉這些函式。


3.2 變更物件的長度

一個「空的」物件可能仍有模式。例如

> e <- numeric()

會讓 e 成為一個數值模式的空向量結構。類似地,character() 是個空的字元向量,以此類推。一旦建立任何大小的物件後,只要給它先前範圍外的索引值,就可以新增新的組成部分。因此

> e[3] <- 17

現在會讓 e 變成長度為 3 的向量(其前兩個組成部分在這個時間點都是 NA)。這適用於任何結構,前提是額外組成部分的模式一開始與物件的模式一致。

這種自動調整物件長度的做法很常使用,例如在 scan() 函式的輸入中。(請參閱 函式 scan()。)

相反地,要截斷物件的大小,只需要做一次指定。因此,如果 alpha 是長度為 10 的物件,則

> alpha <- alpha[2 * 1:5]

會讓它變成長度為 5 的物件,只包含原先偶數索引的組成部分。(舊的索引當然不會保留。)然後,我們可以只保留前三個值,方法如下:

> length(alpha) <- 3

,而向量也可以用相同的方式延伸(透過遺漏值)。


3.3 取得和設定屬性

函數 attributes(object) 會傳回目前為該物件定義的所有非內建屬性的清單。函數 attr(object, name) 可用於選取特定屬性。這些函數很少使用,除非在某些特殊情況下,例如為某個特定目的建立新的屬性,例如將建立日期或操作者與 R 物件關聯。然而,這個概念非常重要。

指定或刪除屬性時應小心,因為它們是 R 中所使用物件系統的組成部分。

當在指定項目的左側使用時,它可用於將新的屬性與 object 關聯,或變更現有的屬性。例如

> attr(z, "dim") <- c(10,10)

允許 R 將 z 視為 10x10 矩陣。


3.4 物件的類別

R 中的所有物件都有 類別,由函數 class 報告。對於簡單向量,這只是模式,例如 "numeric""logical""character""list",但 "matrix""array""factor""data.frame" 是其他可能的值。

一個稱為 類別 的特殊屬性用於允許 R 中面向物件的程式設計風格13。例如,如果一個物件具有類別 "data.frame",它將以特定方式列印,plot() 函數將以特定方式以圖形方式顯示它,而其他所謂的通用函數(例如 summary())會對它作為一個參數做出對其類別敏感的反應。

若要暫時移除類別的效果,請使用函數 unclass() 例如,如果 winter 具有類別 "data.frame",則

> winter

將以資料框形式列印它,這有點像矩陣,而

> unclass(winter)

將以一般清單的形式列印它。只有在相當特殊的情況下,您才需要使用此功能,但其中一項是當您正在學習了解類別和通用函數的概念時。

通用函數和類別將在 類別、通用函數和物件導向 中進一步討論,但僅簡要說明。


4 有序和無序因子

因子 是一個向量物件,用於指定相同長度之其他向量的組成部分的離散分類(群組)。R 提供了有序無序因子。雖然因子的「實際」應用是模型公式(請參閱 對比),但我們在此查看一個具體的範例。

4.1 具體範例

例如,假設我們有來自澳洲所有州和領地的 30 位稅務會計師的樣本14,且其個別的原屬州別由一個字元向量的州縮寫指定,如下所示:

> state <- c("tas", "sa",  "qld", "nsw", "nsw", "nt",  "wa",  "wa",
             "qld", "vic", "nsw", "vic", "qld", "qld", "sa",  "tas",
             "sa",  "nt",  "wa",  "vic", "qld", "nsw", "nsw", "wa",
             "sa",  "act", "nsw", "vic", "vic", "act")

請注意,對於字元向量而言,「已排序」表示已按字母順序排序。

同樣地,可以使用 factor() 函數建立一個 因子

> statef <- factor(state)

函數 print() 處理因子的方式與其他物件略有不同

> statef
 [1] tas sa  qld nsw nsw nt  wa  wa  qld vic nsw vic qld qld sa
[16] tas sa  nt  wa  vic qld nsw nsw wa  sa  act nsw vic vic act
Levels:  act nsw nt qld sa tas vic wa

可以使用函數 levels() 來找出因子的層級。

> levels(statef)
[1] "act" "nsw" "nt"  "qld" "sa"  "tas" "vic" "wa"

4.2 函數 tapply() 和不規則陣列

繼續上一個範例,假設我們在另一個向量中擁有相同稅務會計師的收入(以適當的大金額單位表示)

> incomes <- c(60, 49, 40, 61, 64, 60, 59, 54, 62, 69, 70, 42, 56,
               61, 61, 61, 58, 51, 48, 65, 49, 49, 41, 48, 52, 46,
               59, 46, 58, 43)

現在,我們可以使用特殊函數 tapply() 來計算每個州的平均收入樣本

> incmeans <- tapply(incomes, statef, mean)

產生一個平均值向量,其組成部分由層級標記

   act    nsw     nt    qld     sa    tas    vic     wa
44.500 57.333 55.500 53.600 55.000 60.500 56.000 52.250

函數 tapply() 用於將函數(這裡為 mean())套用至第一個引數(這裡為 incomes)的每個組成部分群組,由第二個組成部分(這裡為 statef)的層級定義15,就好像它們是獨立的向量結構。結果是一個結構,其長度與因子的層級屬性相同,且包含結果。讀者應參閱說明文件以取得更多詳細資料。

假設我們進一步需要計算州所得平均值的標準誤差。為此,我們需要撰寫一個 R 函數來計算任何給定向量的標準誤差。由於有一個內建函數 var() 來計算樣本變異數,因此這樣的函數是一個非常簡單的一行函數,由指定指定

> stdError <- function(x) sqrt(var(x)/length(x))

(撰寫函數將在 撰寫您自己的函數 中後續說明。請注意,R 的內建函數 sd() 是不同的東西。) 在此指定後,標準誤差會透過下列方式計算

> incster <- tapply(incomes, statef, stdError)

然後計算的值為

> incster
act    nsw  nt    qld     sa tas   vic     wa
1.5 4.3102 4.5 4.1061 2.7386 0.5 5.244 2.6575

作為練習,您可能會想要找出州平均所得的通常 95% 信賴區間。為此,您可以再次使用 tapply() 搭配 length() 函數來找出樣本大小,並使用 qt() 函數來找出適當的 t 分配的百分比點。(您也可以調查 R 的 t 檢定的功能。)

函數 tapply() 也可用於處理向量透過多個類別進行更複雜的索引。例如,我們可能希望依據州和性別來區分稅務會計師。然而,在此簡單的範例中(僅一個因子),所發生的情況可以想像如下。向量中的值會收集到與因子中不同條目對應的群組。然後函數會個別套用於這些群組中的每個群組。值是函數結果的向量,標籤為因子的 levels 屬性。

向量和標籤因子的組合是一個有時稱為 參差不齊陣列 的範例,因為子類別大小可能不規則。當子類別大小都相同時,索引可以隱含且更有效率地完成,如我們在下一節中所見。


4.3 已排序因子

因子的層級以字母順序儲存,或依據明確指定給 factor 的順序儲存(如果它們是明確指定的)。

有時層級會具有我們想要記錄並希望我們的統計分析加以利用的自然排序。 ordered() 函數會建立此類已排序因子,但其他方面與 factor 相同。在多數情況下,已排序因子和未排序因子之間唯一的差異在於,已排序因子會顯示層級排序,但為其在線性模型中產生的對比則不同。


5 陣列和矩陣


5.1 陣列

陣列可以視為多重標記的資料項目集合,例如數字。R 允許使用簡單的工具來建立和處理陣列,特別是矩陣這種特殊情況。

維度向量是非負整數的向量。如果其長度為 k,則陣列為 k 維,例如矩陣為 2 維陣列。維度從一編號到維度向量中給定的值。

向量只能在具有維度向量作為其 dim 屬性的情況下,才能被 R 當作陣列使用。例如,假設 z 是包含 1500 個元素的向量。賦值

> dim(z) <- c(3,5,100)

賦予其 dim 屬性,使其可以被視為 3 乘以 5 乘以 100 的陣列。

其他函數(例如 matrix()array())可用於更簡單且外觀更自然的賦值,我們將在 函數 array() 中看到。

資料向量中的值會以與在 FORTRAN 中出現的順序相同的順序提供陣列中的值,也就是「列優先順序」,第一個下標變動最快,最後一個下標變動最慢。

例如,如果陣列的維度向量,假設為 a,是 c(3,4,2),則 a 中有 3 * 4 * 2 = 24 個項目,而資料向量會以 a[1,1,1], a[2,1,1], …, a[2,4,2], a[3,4,2] 的順序儲存這些項目。

陣列可以是一維的:此類陣列通常會以與向量相同的方式處理(包括列印時),但例外情況可能會造成混淆。


5.2 陣列索引。陣列的子區段

陣列的個別元素可以透過提供陣列名稱,後接方括號中的下標(以逗號分隔)來參照。

更普遍來說,陣列的子區段可以透過提供一系列的索引向量來指定,取代下標;但是,如果任何索引位置給予一個空索引向量,則會採用該下標的完整範圍

延續前一個範例,a[2,,] 是維度向量為 c(4,2) 的 4 * 2 陣列,而資料向量包含按該順序排列的值。

c(a[2,1,1], a[2,2,1], a[2,3,1], a[2,4,1],
  a[2,1,2], a[2,2,2], a[2,3,2], a[2,4,2])

a[,,] 代表整個陣列,這與完全省略下標並單獨使用 a 相同。

對於任何陣列,例如 Z,維度向量可以明確地作為 dim(Z) 參照(在指定兩側)。

此外,如果陣列名稱僅給出 一個下標或索引向量,則僅使用資料向量的對應值;在此情況下,維度向量將被忽略。不過,如果單一索引不是向量,而是陣列本身,則並非如此,如下所述。


5.3 索引矩陣

除了在任何下標位置的索引向量之外,還可以將矩陣與單一的 索引矩陣 一起使用,以便將數量向量指定給陣列中元素的不規則集合,或將不規則集合作為向量提取出來。

矩陣範例可以清楚說明這個過程。在雙重索引陣列的情況下,可以給出由兩列和任意多行組成的索引矩陣。索引矩陣中的條目是雙重索引陣列的列索引和行索引。例如,假設我們有一個 4 乘以 5 的陣列 X,我們希望執行以下操作

  • 將元素 X[1,3]X[2,2]X[3,1] 作為向量結構提取出來,以及
  • 用零取代陣列 X 中的這些條目。

在這種情況下,我們需要一個 3 乘以 2 的下標陣列,如下面的範例所示。

> x <- array(1:20, dim=c(4,5))   # Generate a 4 by 5 array.
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> i <- array(c(1:3,3:1), dim=c(3,2))
> i                             # i is a 3 by 2 index array.
     [,1] [,2]
[1,]    1    3
[2,]    2    2
[3,]    3    1
> x[i]                          # Extract those elements
[1] 9 6 3
> x[i] <- 0                     # Replace those elements by zeros.
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    0   13   17
[2,]    2    0   10   14   18
[3,]    0    7   11   15   19
[4,]    4    8   12   16   20
>

索引矩陣中不允許使用負數索引。允許使用 NA 和零值:包含零值的索引矩陣中的列會被忽略,而包含 NA 的列會在結果中產生 NA

舉一個不太平凡的範例,假設我們希望為由因子 blocksb 個層級)和 varietiesv 個層級)定義的區塊設計產生一個(未簡約)的設計矩陣。進一步假設實驗中有 n 個區塊。我們可以進行以下步驟

> Xb <- matrix(0, n, b)
> Xv <- matrix(0, n, v)
> ib <- cbind(1:n, blocks)
> iv <- cbind(1:n, varieties)
> Xb[ib] <- 1
> Xv[iv] <- 1
> X <- cbind(Xb, Xv)

若要建構發生矩陣,假設為 N,我們可以使用

> N <- crossprod(Xb, Xv)

然而,產生此矩陣的一個更簡單的直接方法是使用 table()

> N <- table(blocks, varieties)

索引矩陣必須是數值的:任何其他形式的矩陣(例如邏輯或字元矩陣)作為矩陣提供時,會被視為索引向量。


5.4 array() 函數

除了給向量結構一個 dim 屬性之外,陣列也可以由 array 函數從向量建構,其形式如下

> Z <- array(data_vector, dim_vector)

例如,如果向量 h 包含 24 個或更少的數字,則命令

> Z <- array(h, dim=c(3,4,2))

將使用 hZ 中設定一個 342 的陣列。如果 h 的大小恰好為 24,則結果與

> Z <- h ; dim(Z) <- c(3,4,2)

然而,如果 h 短於 24,其值會從開頭開始再次循環,以使其達到大小 24(請參閱 混合向量和陣列算術。循環規則),但 dim(h) <- c(3,4,2) 會發出關於長度不匹配的錯誤訊息。一個極端但常見的範例

> Z <- array(0, c(3,4,2))

會讓 Z 成為一個全零陣列。

此時 dim(Z) 代表維度向量 c(3,4,2),而 Z[1:24] 代表資料向量,就像在 h 中一樣,而帶有空下標的 Z[] 或沒有下標的 Z 代表整個陣列作為一個陣列。

陣列可以用於算術表達式中,而結果會是一個陣列,由資料向量的逐元素運算形成。運算元的 dim 屬性通常需要相同,而這會成為結果的維度向量。因此,如果 ABC 都是類似的陣列,則

> D <- 2*A*B + C + 1

會讓 D 成為一個類似的陣列,其資料向量是給定逐元素運算的結果。然而,關於混合陣列和向量計算的精確規則必須更仔細地考慮。


5.4.1 混合向量和陣列算術。循環規則

影響元素依元素混合計算的精確規則與向量和陣列有點古怪,且在參考中很難找到。根據經驗,我們發現以下為可靠的指南。

  • 表達式從左到右掃描。
  • 任何短向量運算元都透過回收其值來延伸,直到與任何其他運算元的尺寸相符。
  • 只要遇到短向量和陣列而已,陣列必須全部具有相同的dim屬性,否則會產生錯誤。
  • 任何比矩陣或陣列運算元長的向量運算元都會產生錯誤。
  • 如果存在陣列結構,且沒有發生錯誤或強制轉換為向量,則結果會是陣列結構,其陣列運算元的dim屬性相同。

5.5 兩陣列的外積

陣列上的重要運算為外積。如果ab是兩個數值陣列,它們的外積是一個陣列,其維度向量是透過串接它們兩個維度向量(順序很重要)而獲得的,而其資料向量則是透過形成a的資料向量的元素與b的資料向量元素的所有可能乘積而獲得的。外積是由特殊運算子%o%形成的:

> ab <- a %o% b

另一種方法為:

> ab <- outer(a, b, "*")

乘法函數可以替換為兩個變數的任意函數。例如,如果我們希望評估函數 f(x; y) = cos(y)/(1 + x^2) 在值的有序網格上,其中xy坐標分別由 R 向量xy定義,我們可以執行下列動作

> f <- function(x, y) cos(y)/(1 + x^2)
> z <- outer(x, y, f)

特別是兩個普通向量的外積是雙重下標陣列(也就是矩陣,秩最多為 1)。請注意,外積運算子當然是非交換的。在撰寫您自己的函數中,將進一步探討定義您自己的 R 函數。

範例:2 乘 2 單位數字矩陣的行列式

作為一個人工但可愛的範例,考慮22 矩陣[a, b; c, d]的行列式,其中每個項目都是範圍0, 1, ..., 9中的非負整數,也就是數字。

問題是要找出所有此形式的矩陣的行列式ad - bc,並將每個值發生的頻率表示為高密度繪圖。這等於找出行列式的機率分佈,如果每個數字都是獨立且均勻地隨機選擇。

執行此項操作的簡潔方法是使用outer()函數兩次

> d <- outer(0:9, 0:9)
> fr <- table(outer(d, d, "-"))
> plot(fr, xlab="Determinant", ylab="Frequency")

請注意,這裡的 plot() 使用類似於直方圖的繪製方法,因為它「看到」fr"table" 類別。使用 for 迴圈執行此問題的「顯而易見」方法,將在 分組、迴圈和條件執行 中討論,效率太低,不切實際。

另外,令人驚訝的是,大約 20 個此類矩陣中就有 1 個是奇異矩陣。


5.6 陣列的廣義轉置

函數 aperm(a, perm) 可用於排列陣列 a。參數 perm 必須是整數 {1, ..., k} 的排列,其中 ka 中下標的數量。函數的結果是一個與 a 大小相同的陣列,但舊維度由 perm[j] 給定,成為新的第 j 維。最容易想到這個運算的方式是將其視為矩陣轉置的廣義化。事實上,如果 A 是矩陣(也就是雙下標陣列),則由下式給出的 B

> B <- aperm(A, c(2,1))

只是 A 的轉置。對於這個特殊情況,一個更簡單的函式 t() 可用,因此我們可以使用 B <- t(A)


5.7 矩陣工具

如上所述,矩陣只是一個具有兩個下標的陣列。然而,它是一個非常重要的特殊情況,需要單獨討論。R 包含許多僅對矩陣可用的運算子和函式。例如 t(X) 是矩陣轉置函式,如上所述。函式 nrow(A)ncol(A) 分別給出矩陣 A 中的行數和列數。


5.7.1 矩陣乘法

運算子 %*% 用於矩陣乘法。 當然,n11n 矩陣可以用作 n 向量,如果在上下文中這樣做是適當的。相反,出現在矩陣乘法表達式中的向量會自動提升為行向量或列向量,如果可能的話,無論哪個在乘法上是一致的(儘管這並不總是明確可能的,正如我們稍後看到的)。

例如,如果 AB 是相同大小的方陣,則

> A * B

是元素乘積矩陣,而

> A %*% B

是矩陣乘積。如果 x 是向量,則

> x %*% A %*% x

是一個二次型。16

函數 crossprod() 形成「叉積」,意思是 crossprod(X, y)t(X) %*% y 相同,但運算更有效率。如果省略 crossprod() 的第二個參數,則假設它與第一個參數相同。

diag() 的含義取決於它的參數。 diag(v),其中 v 是向量,給出一個對角矩陣,其中向量的元素作為對角線條目。另一方面,diag(M),其中 M 是矩陣,給出 M 的主對角線條目的向量。這與 MATLABdiag() 使用的慣例相同。此外,有點令人困惑的是,如果 k 是單個數值,則 diag(k)kk 的單位矩陣!


5.7.2 線性方程式與反矩陣

求解線性方程式是矩陣乘法的反運算。當

> b <- A %*% x

只有 Ab 已知時,向量 x 就是該線性方程式組的解。在 R 中,

> solve(A,b)

求解該方程式組,傳回 x(會有些許精確度損失)。請注意,在線性代數中,正式的寫法是 x = A^{-1} %*% b,其中 A^{-1} 表示 A反矩陣,其計算方式為

solve(A)

但很少需要用到。在數值上,計算 x <- solve(A) %*% b 既沒有效率,而且可能不穩定,不如使用 solve(A,b)

二次形式  x %*% A^{-1} %*% x   用於多變量運算中,應該使用類似17 x %*% solve(A,x) 的方式計算,而不是計算 A 的反矩陣。


5.7.3 特徵值與特徵向量

函數 eigen(Sm) 會計算對稱矩陣 Sm 的特徵值與特徵向量。此函數的結果是一個清單,包含兩個名為 valuesvectors 的元件。指定

> ev <- eigen(Sm)

將此清單指定給 ev。然後 ev$valSm 的特徵值向量,而 ev$vec 是對應特徵向量的矩陣。如果我們只需要特徵值,則可以使用指定

> evals <- eigen(Sm)$values

evals 現在包含特徵值向量,而第二個組件則會捨棄。如果表示式

> eigen(Sm)

本身用作命令,則會印出兩個組件及其名稱。對於大型矩陣,如果不需要特徵向量,最好使用表示式來避免計算特徵向量

> evals <- eigen(Sm, only.values = TRUE)$values

5.7.4 奇異值分解與行列式

函數 svd(M) 採用任意矩陣引數 M,並計算 M 的奇異值分解。這包含一個正交欄矩陣 U,其欄位空間與 M 相同,一個第二個正交欄矩陣 V,其欄位空間是 M 的列空間,以及一個正項目的對角線矩陣 D,使得 M = U %*% D %*% t(V)D 實際上以對角線元素的向量形式回傳。 svd(M) 的結果實際上是一個清單,包含三個組件,分別命名為 duv,其意義顯而易見。

如果 M 實際上是方陣,那麼不難看出

> absdetM <- prod(svd(M)$d)

計算 M 行列式的絕對值。如果需要使用各種矩陣經常進行此計算,則可以將其定義為 R 函數

> absdet <- function(M) prod(svd(M)$d)

之後我們可以使用 absdet() 作為另一個 R 函數。作為進一步簡單但潛在有用的範例,您可能想要考慮撰寫一個函數,例如 tr(),來計算方陣的跡數。[提示:您不需要使用明確的迴圈。請再查看 diag() 函數。]

R 有內建函數 det 來計算行列式,包括符號,以及另一個 determinant,提供符號和模數(選擇性地以對數刻度顯示),


5.7.5 最小平方法擬合和 QR 分解

函數 lsfit() 傳回一個清單,提供最小平方法擬合程序的結果。指定如下

> ans <- lsfit(X, y)

提供最小平方法擬合的結果,其中 y 是觀察向量,而 X 是設計矩陣。請參閱說明工具以取得更多詳細資料,以及後續函數 ls.diag(),以取得迴歸診斷等資訊。請注意,總平均值會自動納入,不需要明確地包含在 X 的欄中。請進一步注意,您幾乎總是會偏好使用 lm(.)(請參閱 線性模型)而非 lsfit() 來進行迴歸建模。

另一個密切相關的函數是 qr() 及其相關函數。考慮以下指定

> Xplus <- qr(X)
> b <- qr.coef(Xplus, y)
> fit <- qr.fitted(Xplus, y)
> res <- qr.resid(Xplus, y)

這些計算 yfit 中的 X 範圍內的正交投影、在 res 中的正交補數上的投影,以及在 b 中的投影係數向量,也就是說,b 基本上是 MATLAB「反斜線」運算子的結果。

不假設 X 具有完整的列秩。將會在發現冗餘時發現並移除它們。

這個替代方法是執行最小平方法計算的較舊、較低階的方式。儘管在某些情況下仍然有用,但現在通常會被統計模型功能取代,如 R 中的統計模型 中所討論的。


5.8 形成分割矩陣,cbind()rbind()

正如我們已經非正式地看到的,矩陣可以透過函數 cbind()rbind() 從其他向量和矩陣建立。大致上,cbind() 透過水平或按欄位結合矩陣來形成矩陣,而 rbind() 則垂直或按列結合。

在指定中

> X <- cbind(arg_1, arg_2, arg_3, ...)

cbind() 的引數必須是任何長度的向量,或具有相同欄位大小(即相同列數)的矩陣。結果是一個矩陣,其中串接的引數 arg_1arg_2、… 形成欄位。

如果 cbind() 的某些引數是向量,它們可能比任何現有矩陣的欄位大小短,這種情況下,它們會循環延伸以符合矩陣欄位大小(或在沒有給定矩陣時符合最長向量的長度)。

函數 rbind() 對列執行對應的操作。在這種情況下,任何向量引數(可能循環延伸)當然被視為列向量。

假設 X1X2 具有相同數量的列。若要將這些資料依照欄位合併成矩陣 X,以及一欄初始的 1,我們可以使用

> X <- cbind(1, X1, X2)

使用 rbind()cbind() 的結果總是具有矩陣狀態。因此 cbind(x)rbind(x) 可能分別是允許向量 x 被視為欄或列矩陣的最簡單方式。


5.9 串接函數 c() 與陣列

應注意,雖然 cbind()rbind() 是串接函數,會尊重 dim 屬性,但基本 c() 函數不會,而是會清除所有 dimdimnames 屬性的數字物件。這偶爾很有用。

將陣列強制轉換回簡單向量物件的官方方式是使用 as.vector()

> vec <- as.vector(X)

然而,也可以使用只有一個參數的 c() 函數來達成類似的結果,單純為了這個副作用

> vec <- c(X)

兩者之間有細微的差異,但最終選擇哪一個在很大程度上取決於風格(前者較佳)。


5.10 從因子建立頻率表

回想一下,因子定義為將資料分組。同樣地,一對因子定義為雙向交叉分類,以此類推。 函數 table() 允許從等長因子計算頻率表。如果存在 k 個因子參數,則結果是一個 k 維頻率陣列。

例如,假設 statef 是提供資料向量中每個條目的州代碼的因子。指定

> statefr <- table(statef)

statefr 中給出樣本中每個州的頻率表。這些頻率由因子的 levels 屬性排序並標記。這個簡單的案例等同於以下案例,但更方便:

> statefr <- tapply(statef, statef, length)

進一步假設 incomef 是提供資料向量中每個條目的適當定義的「所得類別」的因子,例如使用 cut() 函數

> factor(cut(incomes, breaks = 35+10*(0:7))) -> incomef

然後計算雙向頻率表

> table(incomef,statef)
         statef
incomef   act nsw nt qld sa tas vic wa
  (35,45]   1   1  0   1  0   0   1  0
  (45,55]   1   1  1   1  2   0   1  3
  (55,65]   0   3  1   3  2   2   2  1
  (65,75]   0   1  0   0  0   0   1  0

立即擴展到更高維度的頻率表。


6 清單和資料框


6.1 清單

R 清單是一個物件,包含一個稱為其元件的有序物件集合。

元件沒有特別需要具有相同的模式或類型,例如,一個清單可以包含一個數字向量、一個邏輯值、一個矩陣、一個複數向量、一個字元陣列、一個函數,等等。以下是一個建立清單的簡單範例

> Lst <- list(name="Fred", wife="Mary", no.children=3,
              child.ages=c(4,7,9))

元件總是編號,並且總是可以用編號來參考。因此,如果Lst是一個具有四個元件的清單名稱,這些元件可以個別稱為Lst[[1]]Lst[[2]]Lst[[3]]Lst[[4]]。此外,如果Lst[[4]]是一個向量下標陣列,則Lst[[4]][1]是其第一個輸入。

如果Lst是一個清單,則函數length(Lst)會提供其(頂層)元件的數量。

清單的元件也可以命名,在這種情況下,元件可以透過在雙方括號中輸入字元字串作為數字,或更方便地,透過提供以下形式的表達式來參考

> name$component_name

用於相同的事物。

這是一個非常有用的慣例,因為如果你忘記數字,它可以讓你更容易取得正確的元件。

因此,在上面給出的簡單範例中

Lst$nameLst[[1]]相同,並且是字串"Fred"

Lst$wifeLst[[2]]相同,並且是字串"Mary"

Lst$child.ages[1]Lst[[4]][1] 相同,都是數字 4

此外,也可以在雙中括號中使用清單組件的名稱,例如 Lst[["name"]]Lst$name 相同。當要萃取的組件名稱儲存在另一個變數中時,這特別有用,如下所示:

> x <- "name"; Lst[[x]]

區分 Lst[[1]]Lst[1] 非常重要。‘[[]]’ 是用於選取單一元素的運算子,而 ‘[]’ 是一般性的下標運算子。因此,前者是 清單 Lst 中的第一個物件,如果它是命名清單,則 包含名稱。後者是 清單 Lst 的子清單,僅包含第一個項目。如果它是命名清單,則名稱會傳輸到子清單。

組件的名稱可以縮寫為識別它們所需的最小字母數。因此,Lst$coefficients 可以簡要指定為 Lst$coeLst$covariance 可以指定為 Lst$cov

名稱向量實際上只是清單的屬性,就像其他屬性一樣,可以這樣處理。當然,除了清單之外的其他結構也可以給予 names 屬性。


6.2 建構和修改清單

可透過函數 list() 從現有物件建立新清單。形式如

> Lst <- list(name_1=object_1, ..., name_m=object_m)

設定清單 Lst,包含 m 個元件,使用 object_1,…,object_m 作為元件,並根據引數名稱指定名稱(可自由選擇)。如果省略這些名稱,元件只會編號。用於建立清單的元件在建立新清單時會複製,而不會影響原始元件。

清單(就像任何有下標的物件)可以透過指定額外元件來延伸。例如

> Lst[5] <- list(matrix=Mat)

6.2.1 串接清單

當串接函數 c() 給定清單引數時,結果也是模式為清單的物件,其元件是引數清單的元件按順序串接而成的。

> list.ABC <- c(list.A, list.B, list.C)

回想一下,當引數為向量物件時,串接函數也會以類似的方式將所有引數串接成單一向量結構。在此情況下,所有其他屬性(例如 dim 屬性)都會被捨棄。


6.3 資料框

一個 資料框 是具有 "data.frame" 類別的清單。對於可以製成資料框的清單有一些限制,即

  • 組成必須是向量(數值、字元或邏輯)、因子、數值矩陣、清單或其他資料框。
  • 矩陣、清單和資料框分別提供與它們的欄、元素或變數一樣多的變數給新的資料框。
  • 出現在資料框變數中的向量結構都必須具有 相同的長度,而矩陣結構都必須具有 相同的列數

對於許多目的來說,資料框可以視為一個欄可能具有不同模式和屬性的矩陣。它可以顯示為矩陣形式,並使用矩陣索引慣例來擷取其列和欄。


6.3.1 建立資料框

滿足資料框欄(組成)限制的物件可以使用函式 data.frame 來形成一個資料框:

> accountants <- data.frame(home=statef, loot=incomes, shot=incomef)

組成符合資料框限制的清單可以使用函式 as.data.frame() 強制轉換成資料框。

從頭建立資料架構最簡單的方法,就是使用 read.table() 函數從外部檔案讀取整個資料架構。這部分將在 從檔案讀取資料 中進一步說明。


6.3.2 attach()detach()

清單元件的 $ 表示法(例如 accountants$home)並不總是十分方便。一個有用的功能是,讓清單或資料架構的元件暫時以其元件名稱顯示為變數,而無需每次都明確引用清單名稱。

attach() 函數以「資料庫」(例如清單或資料架構)作為其引數。因此,假設 lentils 是具有三個變數 lentils$ulentils$vlentils$w 的資料架構。attach

> attach(lentils)

將資料架構置於搜尋路徑中的位置 2,並且如果位置 1 中沒有變數 uvw,則 uvw 可作為資料架構中的變數自行使用。此時,類似下列的指定

> u <- v+w

並不會取代資料架構的元件 u,而是使用搜尋路徑上位置 1 的另一個變數 u 將其遮蔽。若要對資料架構本身進行永久變更,最簡單的方法是再次使用 $ 表示法

> lentils$u <- v+w

然而,元件 u 的新值在資料框分離並重新附加之前不會顯示。

若要分離資料框,請使用函數

> detach()

更精確地說,此陳述會從搜尋路徑中分離目前位於位置 2 的實體。因此,在目前的情境中,變數 uvw 將不再顯示,除非使用清單表示法,例如 lentils$u 等。搜尋路徑上大於 2 的位置的實體可透過提供其數字給 detach 來分離,但永遠使用名稱會安全得多,例如 detach(lentils)detach("lentils")

注意:在 R 中,清單和資料框只能附加在位置 2 或以上,而附加的內容是原始物件的 副本。您可以透過 assign 變更附加的值 via,但原始清單或資料框不會變更。


6.3.3 使用資料框

一個實用的慣例,讓您可以在同一個工作區中舒適地處理許多不同的問題,如下:

  • 將任何定義良好且獨立問題的所有變數收集在一個資料框中,並使用適當的資訊性名稱;
  • 在處理問題時,將適當的資料框附加在位置 2,並將層級 1 的工作區用於運算數量和暫時變數;
  • 在離開問題之前,使用 $ 形式的指定將您希望保留以供未來參考的任何變數新增到資料框,然後 detach()
  • 最後,從工作區中移除所有不需要的變數,並盡可能保持其不殘留任何暫時變數。

如此一來,在同一個目錄中處理多個問題會變得相當簡單,例如,所有問題的變數名稱都為 xyz


6.3.4 附加任意清單

attach() 是一個通用函數,它不僅允許將目錄和資料框附加到搜尋路徑,還可以附加其他類型的物件。特別是,任何模式為 "list" 的物件都可以用相同的方式附加

> attach(any.old.list)

任何已附加的項目都可以透過 detach、位置編號或(優先)名稱來分離。


6.3.5 管理搜尋路徑

函數 search 會顯示目前的搜尋路徑,因此是很好的方式,可以追蹤哪些資料框和清單(以及套件)已附加和分離。最初,它會提供

> search()
[1] ".GlobalEnv"   "Autoloads"    "package:base"

其中 .GlobalEnv 是工作區。18

附加 lentils 之後,我們有

> search()
[1] ".GlobalEnv"   "lentils"      "Autoloads"    "package:base"
> ls(2)
[1] "u" "v" "w"

而且正如我們所見,ls(或 objects)可於搜尋路徑中檢查任何位置的內容。

最後,我們分離資料框,並確認已將其從搜尋路徑中移除。

> detach("lentils")
> search()
[1] ".GlobalEnv"   "Autoloads"    "package:base"

7 從檔案讀取資料

大型資料物件通常會從外部檔案讀取為值,而不是在 R 會話期間於鍵盤上輸入。R 輸入功能很簡單,其需求相當嚴格,甚至有點不靈活。R 的設計者明顯假設您將能夠使用其他工具(例如檔案編輯器或 Perl19)修改輸入檔案,以符合 R 的需求。這通常非常簡單。

如果變數主要保存在資料框中,正如我們強烈建議的那樣,可以使用 read.table() 函數直接讀取整個資料框。還有一個更原始的輸入函數 scan(),可以直接呼叫。

有關將資料匯入 R 以及匯出資料的更多詳細資訊,請參閱R 資料匯入/匯出手冊。


7.1 函數 read.table()

若要直接讀取整個資料框,外部檔案通常會有特殊格式。

  • 檔案的第一行應為資料框中每個變數的名稱
  • 檔案的每一行額外項目,第一個項目為列標籤,以及每個變數的值。

如果檔案的第一行比第二行少一個項目,則假設採用這種配置。因此,要作為資料框讀取的檔案的前幾行可能如下所示。

Input file form with names and row labels:

     Price    Floor     Area   Rooms     Age  Cent.heat
01   52.00    111.0      830     5       6.2      no
02   54.75    128.0      710     5       7.5      no
03   57.50    101.0     1000     5       4.2      no
04   57.50    131.0      690     6       8.8      no
05   59.75     93.0      900     5       1.9     yes
...

預設情況下,數字項目(列標籤除外)會讀取為數字變數,非數字變數(例如範例中的 Cent.heat)會讀取為字元變數。必要時可以變更。

然後可以使用函數 read.table() 直接讀取資料框

> HousePrice <- read.table("houses.data")

通常您會想要省略直接包含列標籤,並使用預設標籤。在這種情況下,檔案可以省略列標籤欄,如下所示。

Input file form without row labels:

Price    Floor     Area   Rooms     Age  Cent.heat
52.00    111.0      830     5       6.2      no
54.75    128.0      710     5       7.5      no
57.50    101.0     1000     5       4.2      no
57.50    131.0      690     6       8.8      no
59.75     93.0      900     5       1.9     yes
...

然後可以讀取資料框,如下所示

> HousePrice <- read.table("houses.data", header=TRUE)

其中 header=TRUE 選項指定第一行為標題行,因此,從檔案的格式中推論,沒有提供明確的列標籤。


7.2 函數 scan()

假設資料向量長度相等,且要並行讀取。進一步假設有三個向量,第一個模式為字元,其餘兩個模式為數字,且檔案為 input.dat。第一步是使用 scan() 將三個向量讀入為一個串列,如下所示

> inp <- scan("input.dat", list("",0,0))

第二個引數是一個虛擬串列結構,用來建立要讀取的這三個向量的模式。儲存在 inp 中的結果是一個串列,其組成部分是讀入的這三個向量。若要將資料項目分開成三個獨立的向量,請使用類似這樣的指定

> label <- inp[[1]]; x <- inp[[2]]; y <- inp[[3]]

更方便的是,虛擬串列可以有命名組成部分,這種情況下可以將名稱用來存取讀入的向量。例如

> inp <- scan("input.dat", list(id="", x=0, y=0))

如果您想要分別存取變數,可以將它們重新指定給工作架構中的變數

> label <- inp$id; x <- inp$x; y <- inp$y

或者,可以將串列附加在搜尋路徑的第 2 個位置(請參閱 附加任意串列)。

如果第二個引數是單一值而不是串列,則會讀入單一向量,其所有組成部分的模式都必須與虛擬值相同。

> X <- matrix(scan("light.dat", 0), ncol=5, byrow=TRUE)

有更多精細的輸入設施可用,這些在手冊中有詳細說明。


7.3 存取內建資料集

R 提供了約 100 個資料集(在套件 datasets 中),其他資料集則在套件中提供(包括 R 提供的建議套件)。若要查看目前可用的資料集清單,請使用

data()

所有 R 提供的資料集都可以直接透過名稱存取。不過,許多套件仍使用已過時的慣例,其中 data 也用於將資料集載入 R 中,例如

data(infert)

這仍然可以用於標準套件(如本範例所示)。在大部分情況下,這會載入同名的 R 物件。不過,在少數情況下,它會載入多個物件,因此請參閱物件的線上說明,以了解會載入哪些內容。

7.3.1 從其他 R 套件載入資料

若要存取特定套件的資料,請使用 package 參數,例如

data(package="rpart")
data(Puromycin, package="datasets")

如果套件已透過 library 附加,其資料集會自動包含在搜尋中。

使用者貢獻的套件可以是資料集的豐富來源。


7.4 編輯資料

當在資料框或矩陣上呼叫 edit 時,會開啟一個獨立的試算表式環境進行編輯。這對於在讀取資料集後進行小幅變更很有用。指令

> xnew <- edit(xold)

會讓您編輯資料集 xold,完成後會將變更後的物件指定給 xnew。如果您想變更原始資料集 xold,最簡單的方法是使用 fix(xold),這等於 xold <- edit(xold)

使用

> xnew <- edit(data.frame())

透過試算表介面輸入新資料。


8 機率分配


8.1 R 作為一組統計表格

R 的一個便利用途是提供一組全面的統計表格。提供函數來評估累積分配函數 P(X <= x)、機率密度函數和分位數函數(給定 q,最小的 x 使得 P(X <= x) > q),並模擬分配。

分配R 名稱其他引數
貝塔貝塔shape1、shape2、ncp
二項binomsize、prob
柯西cauchylocation、scale
卡方chisqdf、ncp
指數exprate
Ffdf1、df2、ncp
伽瑪伽瑪shape、scale
幾何geomprob
超幾何hyperm、n、k
對數常態lnormmeanlog、sdlog
邏輯logislocation、scale
負二項nbinomsize、prob
常態normmean、sd
泊松poislambda
符號等級signrankn
學生 ttdf、ncp
均勻unifmin、max
威布爾weibullshape、scale
威爾科克森wilcoxm、n

在此給定的名稱加上前綴「d」表示密度,「p」表示累積分配函數,「q」表示分位數函數,「r」表示模擬(random deviates)。第一個引數是 x(表示 dxxx),q(表示 pxxx),p(表示 qxxx),n(表示 rxxx)(rhyperrsignrankrwilcox 除外,它們的引數是 nn)。非中心性參數 ncp 目前並非在所有情況下都可用:詳細資訊請參閱線上說明。

函數 pxxxqxxx 都有邏輯參數 lower.taillog.p,而 dxxx 函數有 log。這允許透過以下方式取得累積(或「積分」)風險函數,H(t) = - log(1 - F(t)),

 - pxxx(t, ..., lower.tail = FALSE, log.p = TRUE)

或更精確的對數似然值(透過 dxxx(..., log = TRUE)),直接取得。

此外還有函數 ptukeyqtukey,用於常態分佈樣本的學生化範圍分佈,以及 dmultinomrmultinom,用於多項式分佈。進一步的分佈可以在貢獻套件中取得,特別是 SuppDists

以下是幾個範例

> ## 2-tailed p-value for t distribution
> 2*pt(-2.43, df = 13)
> ## upper 1% point for an F(2, 7) distribution
> qf(0.01, 2, 7, lower.tail = FALSE)

請參閱 RNG 的線上說明,以了解 R 中如何執行亂數產生。


8.2 檢查資料集的分佈

給定一個(單變量)資料集,我們可以用很多方法來檢視其分佈。最簡單的方法是檢視數字。兩個略有不同的摘要由 summaryfivenum 提供,而數字的顯示則由 stem(「莖葉」圖)提供。

> attach(faithful)
> summary(eruptions)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  1.600   2.163   4.000   3.488   4.454   5.100
> fivenum(eruptions)
[1] 1.6000 2.1585 4.0000 4.4585 5.1000
> stem(eruptions)

  The decimal point is 1 digit(s) to the left of the |

  16 | 070355555588
  18 | 000022233333335577777777888822335777888
  20 | 00002223378800035778
  22 | 0002335578023578
  24 | 00228
  26 | 23
  28 | 080
  30 | 7
  32 | 2337
  34 | 250077
  36 | 0000823577
  38 | 2333335582225577
  40 | 0000003357788888002233555577778
  42 | 03335555778800233333555577778
  44 | 02222335557780000000023333357778888
  46 | 0000233357700000023578
  48 | 00000022335800333
  50 | 0370

莖葉圖類似於直方圖,而 R 有函數 hist 來繪製直方圖。

> hist(eruptions)
## make the bins smaller, make a plot of density
> hist(eruptions, seq(1.6, 5.2, 0.2), prob=TRUE)
> lines(density(eruptions, bw=0.1))
> rug(eruptions) # show the actual data points

更精緻的密度圖可以用 density 製作,而我們在這個範例中加入了一條由 density 產生的線。頻寬 bw 是透過試驗和錯誤選取的,因為預設值會產生過多的平滑(對於「有趣的」密度通常會這樣)。(有更好的自動化頻寬選擇方法可用,而在此範例中 bw = "SJ" 會產生良好的結果。)

images/hist

我們可以使用函數 ecdf 來繪製經驗累積分佈函數。

> plot(ecdf(eruptions), do.points=FALSE, verticals=TRUE)

這個分佈顯然遠離任何標準分佈。較右邊的模式呢?例如,超過 3 分鐘的噴發?讓我們擬合一個常態分佈,並疊加擬合的 CDF。

> long <- eruptions[eruptions > 3]
> plot(ecdf(long), do.points=FALSE, verticals=TRUE)
> x <- seq(3, 5.4, 0.01)
> lines(x, pnorm(x, mean=mean(long), sd=sqrt(var(long))), lty=3)
images/ecdf

分位數-分位數(Q-Q)圖可以幫助我們更仔細地檢視這一點。

par(pty="s")       # arrange for a square figure region
qqnorm(long); qqline(long)

顯示出合理的擬合,但右尾比常態分佈預期的要短。讓我們將其與來自 t 分佈的一些模擬資料進行比較

images/QQ
x <- rt(250, df = 5)
qqnorm(x); qqline(x)

這通常會(如果它是一個隨機樣本)顯示比常態預期更長的尾部。我們可以透過以下方式針對產生分佈建立 Q-Q 繪圖

qqplot(qt(ppoints(250), df = 5), x, xlab = "Q-Q plot for t dsn")
qqline(x)

最後,我們可能需要一個更正式的檢定來驗證常態性(或非常態性)。R 提供 Shapiro-Wilk 檢定

> shapiro.test(long)

         Shapiro-Wilk normality test

data:  long
W = 0.9793, p-value = 0.01052

以及 Kolmogorov-Smirnov 檢定

> ks.test(long, "pnorm", mean = mean(long), sd = sqrt(var(long)))

         One-sample Kolmogorov-Smirnov test

data:  long
D = 0.0661, p-value = 0.4284
alternative hypothesis: two.sided

(請注意,由於我們已從同一個樣本估計常態分佈的參數,因此分佈理論在此處無效。)


8.3 單樣本和雙樣本檢定

到目前為止,我們已將單一樣本與常態分佈進行比較。更常見的操作是比較兩個樣本的層面。請注意,在 R 中,所有「古典」檢定(包括以下使用的檢定)都在套件 stats 中,而該套件通常會載入。

考慮以下關於冰的熔解潛熱(cal/gm)的資料集,來自 Rice (1995, p.490)

Method A: 79.98 80.04 80.02 80.04 80.03 80.03 80.04 79.97
          80.05 80.03 80.02 80.00 80.02
Method B: 80.02 79.94 79.98 79.97 79.97 80.03 79.95 79.97

盒狀圖提供兩個樣本的簡單圖形比較。

A <- scan()
79.98 80.04 80.02 80.04 80.03 80.03 80.04 79.97
80.05 80.03 80.02 80.00 80.02

B <- scan()
80.02 79.94 79.98 79.97 79.97 80.03 79.95 79.97

boxplot(A, B)

這表示第一組傾向於提供比第二組更高的結果。

images/ice

若要檢定兩個範例的平均值是否相等,我們可以使用 未配對 t 檢定,方法是

> t.test(A, B)

         Welch Two Sample t-test

data:  A and B
t = 3.2499, df = 12.027, p-value = 0.00694
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.01385526 0.07018320
sample estimates:
mean of x mean of y
 80.02077  79.97875

這表示有顯著差異,假設常態性。預設 R 函數不會假設兩個樣本的變異相等。我們可以使用 F 檢定來檢定變異是否相等,前提是這兩個樣本來自常態母體。

> var.test(A, B)

         F test to compare two variances

data:  A and B
F = 0.5837, num df = 12, denom df =  7, p-value = 0.3938
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
 0.1251097 2.1052687
sample estimates:
ratio of variances
         0.5837405

這顯示沒有顯著差異的證據,因此我們可以使用假設變異相等的古典t檢定。

> t.test(A, B, var.equal=TRUE)

         Two Sample t-test

data:  A and B
t = 3.4722, df = 19, p-value = 0.002551
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.01669058 0.06734788
sample estimates:
mean of x mean of y
 80.02077  79.97875

所有這些檢定都假設兩個樣本的常態性。雙樣本 Wilcoxon(或 Mann-Whitney)檢定僅假設零假設下的共同連續分配。

> wilcox.test(A, B)

         Wilcoxon rank sum test with continuity correction

data:  A and B
W = 89, p-value = 0.007497
alternative hypothesis: true location shift is not equal to 0

Warning message:
Cannot compute exact p-value with ties in: wilcox.test(A, B)

請注意警告:每個樣本中都有多個繫結,這強烈表明這些資料來自離散分配(可能是由於捨入)。

有幾種方法可以圖形化比較兩個樣本。我們已經看過一對箱形圖。下列

> plot(ecdf(A), do.points=FALSE, verticals=TRUE, xlim=range(A, B))
> plot(ecdf(B), do.points=FALSE, verticals=TRUE, add=TRUE)

將顯示兩個經驗 CDF,而qqplot將執行兩個樣本的 Q-Q 圖。Kolmogorov-Smirnov 檢定是兩個 ecdf 之間的最大垂直距離,假設共同連續分配

> ks.test(A, B)

         Two-sample Kolmogorov-Smirnov test

data:  A and B
D = 0.5962, p-value = 0.05919
alternative hypothesis: two-sided

Warning message:
cannot compute correct p-values with ties in: ks.test(A, B)

9 分組、迴圈和條件式執行


9.1 分組運算式

R 是一種運算式語言,因為它唯一的命令類型是會傳回結果的函數或運算式。即使是指定也是一種運算式,其結果是指定的值,而且可以在任何可以使用運算式的地方使用;特別是,可以進行多重指定。

命令可以用大括號分組,{expr_1; ; expr_m},這種情況下,群組的值是群組中最後一個運算式的結果。由於這種群組也是一個運算式,因此它可以包含在括號中,並用作更大運算式的一部分,依此類推。


9.2 控制陳述式


9.2.1 條件式執行:if 陳述式

語言提供形式為

> if (expr_1) expr_2 else expr_3

的條件式結構,其中 expr_1 必須評估為單一邏輯值,然後整個運算式的結果就顯而易見。

「短路」運算子 &&|| 通常用作 if 陳述式中條件的一部分。雖然 &| 對向量逐一元應用,但 &&|| 對長度為一的向量應用,並且僅在必要時評估其第二個引數。

有一個向量化版本的 if/else 建構,ifelse 函數。此函數形式為 ifelse(condition, a, b),並傳回一個與 condition 長度相同的向量,其中元素 a[i]condition[i] 為真時,否則為 b[i](其中 ab 會視需要進行循環利用)。


9.2.2 重複執行:for 迴圈、repeatwhile

還有一個 for 迴圈建構,形式如下:

> for (name in expr_1) expr_2

其中 name 是迴圈變數。expr_1 是向量表達式(通常是類似 1:20 的序列),而 expr_2 通常是群組表達式,其子表達式以虛擬 name 寫成。expr_2 會重複評估,因為 name 遍歷 expr_1 向量結果中的值。

舉例來說,假設 ind 是類別指標的向量,我們希望在類別中產生 yx 的個別繪圖。其中一個可能性是使用 coplot()20 它會產生一個繪圖陣列,對應於因子中的每個層級。另一種方法是將所有繪圖放在同一個顯示器上,如下所示:

> xc <- split(x, ind)
> yc <- split(y, ind)
> for (i in 1:length(yc)) {
    plot(xc[[i]], yc[[i]])
    abline(lsfit(xc[[i]], yc[[i]]))
  }

(注意函數 split(),它會產生一個向量清單,方法是根據因子指定的類別來分割較大的向量。這是一個有用的函數,主要用於箱形圖。有關進一步詳細資訊,請參閱 help 說明。)

警告for() 迴圈在 R 程式碼中使用的頻率遠低於編譯語言。採用「整體物件」觀點的程式碼在 R 中可能更清晰且更快速。

其他迴圈工具包括

> repeat expr

陳述式和

> while (condition) expr

陳述式。

break 陳述式可用於終止任何迴圈,甚至異常終止。這是終止 repeat 迴圈的唯一方法。

next 陳述式可用於中止特定循環並跳到「下一個」。

控制陳述式最常與函式一起使用,函式會在 撰寫您自己的函式 中討論,並會出現更多範例。


10 撰寫您自己的函式

正如我們在過程中非正式地看到的那樣,R 語言允許使用者建立模式為函式的物件。這些是儲存在特殊內部形式的真正 R 函式,可以用於進一步的表達式等等。在此過程中,語言在功能、便利性和優雅性方面大幅提升,而學習撰寫有用的函式是讓您使用 R 舒適且有成效的主要方法之一。

應該強調的是,作為 R 系統一部分提供的函式(例如 mean()var()postscript() 等)本身是用 R 編寫的,因此與使用者撰寫的函式在實質上並無不同。

函數定義為以下形式的指派

> name <- function(arg_1, arg_2, ...) expression

expression 是 R 表達式(通常是群組表達式),使用引數 arg_i 來計算值。表達式的值是函數傳回的值。

呼叫函數通常採用以下形式 name(expr_1, expr_2, …),且可以在函數呼叫合法的任何位置發生。


10.1 簡單範例

作為第一個範例,考量一個函數來計算二樣本 t 統計量,顯示「所有步驟」。這當然是一個人工範例,因為還有其他更簡單的方法可以達成相同的目的。

函數定義如下

> twosam <- function(y1, y2) {
    n1  <- length(y1); n2  <- length(y2)
    yb1 <- mean(y1);   yb2 <- mean(y2)
    s1  <- var(y1);    s2  <- var(y2)
    s <- ((n1-1)*s1 + (n2-1)*s2)/(n1+n2-2)
    tst <- (yb1 - yb2)/sqrt(s*(1/n1 + 1/n2))
    tst
  }

定義此函數後,您可以使用類似以下的呼叫來執行二樣本 t 檢定

> tstat <- twosam(data$male, data$female); tstat

作為第二個範例,考量一個函數來直接模擬 MATLAB 反斜線命令,它會傳回向量 y 在矩陣 X 的欄位空間上的正交投影的係數。(這通常稱為迴歸係數的最小平方估計值。)這通常會使用 qr() 函數來完成;然而,這有時有點難以直接使用,而且有以下簡單函數來安全地使用它會很有幫助。

因此,給定一個 n 乘以 1 的向量 y 和一個 n 乘以 p 的矩陣 X,則 X \ y 被定義為 (X’X)^{-}X’y,其中 (X’X)^{-} 是 X'X 的廣義逆。

> bslash <- function(X, y) {
  X <- qr(X)
  qr.coef(X, y)
}

在建立這個物件之後,它可以在下列陳述中使用,例如

> regcoeff <- bslash(Xmat, yvar)

等等。

傳統的 R 函數 lsfit() 可以很好地完成這項工作,而且更多21。它反過來以稍微反直覺的方式使用函數 qr()qr.coef() 來執行計算的這部分。因此,如果要頻繁使用,將這部分單獨隔離在一個易於使用的函數中可能有些價值。如果是這樣,我們可能希望將它設為矩陣二元運算子,以獲得更方便的使用方式。


10.2 定義新的二元運算子

如果我們給 bslash() 函數一個不同的名稱,即以下形式之一

%anything%

它可以用作表達式中的 二元運算子,而不是函數形式。例如,假設我們選擇 ! 作為內部字元。函數定義將從

> "%!%" <- function(X, y) { ... }

開始(請注意引號的使用方式)。然後函數可以用作 X %!% y。(反斜線符號本身不是一個方便的選擇,因為它在此背景下會產生特殊問題。)

矩陣乘法運算子 %*% 和外積矩陣運算子 %o% 是以這種方式定義的其他二元運算子範例。


10.3 命名參數和預設值

正如在 生成常規序列 中首次提到的,如果傳遞給呼叫函數的參數採用「name=object」形式,則可以按任何順序傳遞這些參數。此外,參數序列可以從未命名的位置形式開始,並在位置參數之後指定命名參數。

因此,如果有一個函數 fun1 由以下定義:

> fun1 <- function(data, data.frame, graph, limit) {
    [function body omitted]
  }

則可以通過多種方式呼叫該函數,例如

> ans <- fun1(d, df, TRUE, 20)
> ans <- fun1(d, df, graph=TRUE, limit=20)
> ans <- fun1(data=d, limit=20, graph=TRUE, data.frame=df)

都是等效的。

在許多情況下,可以為參數指定通常適用的預設值,這種情況下,當預設值適用時,可以從呼叫中完全省略這些參數。例如,如果 fun1 定義如下:

> fun1 <- function(data, data.frame, graph=TRUE, limit=20) { ... }

則可以將其呼叫為

> ans <- fun1(d, df)

現在等效於上述三種情況,或者呼叫為

> ans <- fun1(d, df, limit=10)

這將變更其中一個預設值。

請務必注意,預設值可以是任意表達式,甚至涉及同一函數的其他參數;它們不限於像我們這裡的簡單範例中那樣僅限於常數。


10.4 「」參數

另一個常見的需求是允許一個函數將參數設定傳遞給另一個函數。例如,許多圖形函數使用函數 par(),而函數(例如 plot())允許使用者將圖形參數傳遞給 par() 以控制圖形輸出。(請參閱 永久變更:par() 函數,以取得有關 par() 函數的更多詳細資料。)這可透過包含函數的額外參數(文字上為「」)來完成,然後可以傳遞該參數。以下提供一個大綱範例。

fun1 <- function(data, data.frame, graph=TRUE, limit=20, ...) {
  [omitted statements]
  if (graph)
    par(pch="*", ...)
  [more omissions]
}

較不常見的是,函數需要參照「」的組成部分。表達式 list(...) 會評估所有此類參數並以命名清單的形式傳回,而 ..1..2 等會一次評估一個參數,其中「..n」傳回第 n 個未配對的參數。


10.5 函數內的指定

請注意,在函數內執行的任何一般指定都是區域且暫時的,並且在函數結束後會遺失。因此,指定 X <- qr(X) 不會影響呼叫程式中參數的值。

若要完全了解控制 R 指定範圍的規則,讀者需要熟悉評估架構的概念。這是一個有點進階,但並不困難的主題,而且在此不會進一步探討。

如果要在函數內進行全域且永久的指定,則可以使用「超級指定」運算子 <<- 或函數 assign()。請參閱 help 文件以取得詳細資料。


10.6 更進階的範例


10.6.1 區塊設計中的效率因子

作為一個更完整的函數範例(儘管有點平淡),考慮找出區塊設計的效率因子。(此問題的某些面向已在索引矩陣中討論過。)

區塊設計由兩個因子定義,例如區塊b 層級)和變異v 層級)。如果RKv 乘以vb 乘以b重複區塊大小 矩陣,而Nb 乘以v 的發生矩陣,則效率因子定義為矩陣 E = I_v - R^{-1/2}N’K^{-1}NR^{-1/2} = I_v - A’A 的特徵值,其中 A = K^{-1/2}NR^{-1/2}。以下是撰寫函數的一種方式。

> bdeff <- function(blocks, varieties) {
    blocks <- as.factor(blocks)             # minor safety move
    b <- length(levels(blocks))
    varieties <- as.factor(varieties)       # minor safety move
    v <- length(levels(varieties))
    K <- as.vector(table(blocks))           # remove dim attr
    R <- as.vector(table(varieties))        # remove dim attr
    N <- table(blocks, varieties)
    A <- 1/sqrt(K) * N * rep(1/sqrt(R), rep(b, v))
    sv <- svd(A)
    list(eff=1 - sv$d^2, blockcv=sv$u, varietycv=sv$v)
}

在這種情況下,以奇異值分解運算會比特徵值常式運算好一點。

函數的結果是一個清單,不僅提供效率因子作為第一個組成部分,還提供區塊和變異正規對比,因為有時這些會提供額外的有用定性資訊。


10.6.2 捨棄已列印陣列中的所有名稱

對於大型矩陣或陣列的列印目的,通常會將它們以緊湊的區塊形式列印,而沒有陣列名稱或數字。移除 dimnames 屬性無法達成此效果,而是必須給陣列一個由空字串組成的 dimnames 屬性。例如,要列印一個矩陣 X

> temp <- X
> dimnames(temp) <- list(rep("", nrow(X)), rep("", ncol(X)))
> temp; rm(temp)

這可以用一個函數來完成,如下所示的 no.dimnames(),作為一個「包裝」來達成相同的結果。它也說明了一些有效且有用的使用者函數可以非常簡短。

no.dimnames <- function(a) {
  ## Remove all dimension names from an array for compact printing.
  d <- list()
  l <- 0
  for(i in dim(a)) {
    d[[l <- l + 1]] <- rep("", i)
  }
  dimnames(a) <- d
  a
}

定義此函數後,可以使用以下方式以緊湊格式列印陣列

> no.dimnames(X)

這對於大型整數陣列特別有用,其中模式比值更重要。


10.6.3 遞迴數值積分

函數可以是遞迴的,且可以自行定義函數。但請注意,此類函數或變數不會像在搜尋路徑上一樣,由較高層級評估架構中的呼叫函數繼承。

以下範例顯示執行一維數值積分的一種天真方法。被積分函數在範圍的端點和中間進行評估。如果單區段梯形法則的答案接近雙區段,則後者會作為值傳回。否則,會將相同的程序遞迴套用至每個區段。結果是一個自適應積分程序,會將函數評估集中在被積分函數最遠離線性的區域。但它有很重的負擔,且只有在被積分函數既平滑又非常難以評估時,此函數才具有與其他演算法競爭的優勢。

此範例也部分提供為 R 程式設計中的一個小謎題。

area <- function(f, a, b, eps = 1.0e-06, lim = 10) {
  fun1 <- function(f, a, b, fa, fb, a0, eps, lim, fun) {
    ## function ‘fun1’ is only visible inside ‘area’
    d <- (a + b)/2
    h <- (b - a)/4
    fd <- f(d)
    a1 <- h * (fa + fd)
    a2 <- h * (fd + fb)
    if(abs(a0 - a1 - a2) < eps || lim == 0)
      return(a1 + a2)
    else {
      return(fun(f, a, d, fa, fd, a1, eps, lim - 1, fun) +
             fun(f, d, b, fd, fb, a2, eps, lim - 1, fun))
    }
  }
  fa <- f(a)
  fb <- f(b)
  a0 <- ((fa + fb) * (b - a))/2
  fun1(f, a, b, fa, fb, a0, eps, lim, fun1)
}

10.7 範圍

本節的討論比本文檔的其他部分更具技術性。但它詳述了 S-PLUS 和 R 之間的主要差異之一。

函數主體中出現的符號可分為三類:形式參數、局部變數和自由變數。函數的形式參數是出現在函數參數清單中的參數。它們的值由將實際函數參數繫結到形式參數的繫結程序決定。局部變數的值由函數主體中表達式的評估決定。不是形式參數或局部變數的變數稱為自由變數。如果自由變數被指定,則它們會變成局部變數。考慮下列函數定義。

f <- function(x) {
  y <- 2*x
  print(x)
  print(y)
  print(z)
}

在此函數中,x 是形式參數,y 是局部變數,而 z 是自由變數。

在 R 中,自由變數繫結會先在建立函數的環境中尋找。這稱為詞彙範圍。首先,我們定義一個稱為 cube 的函數。

cube <- function(n) {
  sq <- function() n*n
  n*sq()
}

函數 sq 中的變數 n 不是該函數的參數。因此,它是自由變數,而且必須使用範圍規則來確定與它相關聯的值。在靜態範圍 (S-PLUS) 中,該值與名為 n 的全域變數相關聯。在詞彙範圍 (R) 中,它是函數 cube 的參數,因為在定義函數 sq 時,它是變數 n 的作用中繫結。R 中的評估與 S-PLUS 中的評估之間的差異在於,S-PLUS 會尋找稱為 n 的全域變數,而 R 會先在呼叫 cube 時建立的環境中尋找稱為 n 的變數。

## first evaluation in S
S> cube(2)
Error in sq(): Object "n" not found
Dumped
S> n <- 3
S> cube(2)
[1] 18
## then the same function evaluated in R
R> cube(2)
[1] 8

詞彙範圍也可以用來賦予函數可變狀態。在以下範例中,我們展示 R 如何用來模擬銀行帳戶。一個運作中的銀行帳戶需要有餘額或總額、一個提款功能、一個存款功能和一個陳述目前餘額的功能。我們透過在 account 中建立三個函數,然後傳回包含它們的清單來達成這件事。當呼叫 account 時,它會取得一個數字引數 total,並傳回包含三個函數的清單。由於這些函數是在包含 total 的環境中定義,因此它們可以存取它的值。

特殊指定運算子 <<- 用來變更與 total 相關的值。此運算子會在封閉環境中回溯,尋找包含符號 total 的環境,並且在找到此類環境時,會以右手邊的值取代該環境中的值。如果在沒有找到符號 total 的情況下到達全域或頂層環境,則會建立該變數並指定給它。對大多數使用者而言,<<- 會建立一個全域變數,並將右手邊的值指定給它22。只有在 <<- 用於傳回為另一個函數值函數中時,才會發生此處描述的特殊行為。

open.account <- function(total) {
  list(
    deposit = function(amount) {
      if(amount <= 0)
        stop("Deposits must be positive!\n")
      total <<- total + amount
      cat(amount, "deposited.  Your balance is", total, "\n\n")
    },
    withdraw = function(amount) {
      if(amount > total)
        stop("You don't have that much money!\n")
      total <<- total - amount
      cat(amount, "withdrawn.  Your balance is", total, "\n\n")
    },
    balance = function() {
      cat("Your balance is", total, "\n\n")
    }
  )
}

ross <- open.account(100)
robert <- open.account(200)

ross$withdraw(30)
ross$balance()
robert$balance()

ross$deposit(50)
ross$balance()
ross$withdraw(500)

10.8 自訂環境

使用者可以用好幾種不同的方式自訂他們的環境。有一個網站初始化檔案,而且每個目錄都可以有它自己的特殊初始化檔案。最後,特殊函數 .First.Last 可以使用。

網站初始化檔案的位置取自 R_PROFILE 環境變數的值。如果該變數未設定,則會使用 R 主目錄 etc 中的檔案 Rprofile.site。此檔案應包含您希望每次在您的系統下啟動 R 時執行的指令。第二個個人設定檔檔案名為 .Rprofile23,可以放置在任何目錄中。如果在該目錄中呼叫 R,則會使用該檔案。此檔案讓個別使用者可以控制其工作空間,並允許在不同的工作目錄中使用不同的啟動程序。如果在啟動目錄中找不到 .Rprofile 檔案,則 R 會在使用者的家目錄中尋找 .Rprofile 檔案並使用它(如果存在)。如果設定環境變數 R_PROFILE_USER,則會使用它指向的檔案,而不是 .Rprofile 檔案。

在兩個設定檔檔案或 .RData 映像中,任何名為 .First() 的函數都有特殊狀態。它會在 R 工作階段的開始自動執行,而且可以用來初始化環境。例如,以下範例中的定義會將提示字元變更為 $,並設定其他各種有用的項目,然後可以在工作階段的其餘時間視為理所當然。

因此,檔案執行的順序為 Rprofile.site、使用者設定檔、.RData,然後是 .First()。後續檔案中的定義會遮蓋先前檔案中的定義。

> .First <- function() {
  options(prompt="$ ", continue="+\t")  # $ is the prompt
  options(digits=5, length=999)         # custom numbers and printout
  x11()                                 # for graphics
  par(pch = "+")                        # plotting character
  source(file.path(Sys.getenv("HOME"), "R", "mystuff.R"))
                                        # my personal functions
  library(MASS)                         # attach a package
}

類似地,如果定義了 .Last() 函數,它(通常)會在工作階段的最後執行。以下提供一個範例。

> .Last <- function() {
  graphics.off()                        # a small safety measure.
  cat(paste(date(),"\nAdios\n"))        # Is it time for lunch?
}

10.9 類別、一般函數和物件導向

物件的類別決定了它將如何被稱為 一般 函數處理。換句話說,一般函數對其參數執行特定於參數本身類別的任務或動作。如果參數缺乏任何 class 屬性,或具有特定一般函數未特別提供的類別,則始終會提供 預設動作

一個範例讓事情更清楚。類別機制提供使用者設計和撰寫特殊用途一般函數的功能。其他一般函數包括用於以圖形方式顯示物件的 plot()、用於摘要各種類型分析的 summary(),以及用於比較統計模型的 anova()

可以特定方式處理類別的一般函數數量可能很大。例如,可以容納類別 "data.frame" 物件的函數包括

[     [[<-    any    as.matrix
[<-   mean    plot   summary

可以使用 methods() 函數取得目前完整的清單

> methods(class="data.frame")

相反地,泛函數可以處理的類別數量也可以非常龐大。例如,plot() 函數有一個預設方法和類別物件的變異,例如 "data.frame""density""factor" 等。可以使用 methods() 函數再次取得完整清單

> methods(plot)

對於許多泛函數,函數主體相當簡短,例如

> coef
function (object, ...)
UseMethod("coef")

UseMethod 的存在表示這是泛函數。若要查看有哪些方法可用,我們可以使用 methods()

> methods(coef)
[1] coef.aov*         coef.Arima*       coef.default*     coef.listof*
[5] coef.nls*         coef.summary.nls*

   Non-visible functions are asterisked

在此範例中,有六個方法,輸入其名稱都看不到。我們可以透過下列任一方式來讀取這些方法

> getAnywhere("coef.aov")
A single object matching ‘coef.aov’ was found
It was found in the following places
  registered S3 method for coef from namespace stats
  namespace:stats
with value

function (object, ...)
{
    z <- object$coef
    z[!is.na(z)]
}

> getS3method("coef", "aov")
function (object, ...)
{
    z <- object$coef
    z[!is.na(z)]
}

泛函數 gen 會呼叫名稱為 gen.cl 的函數,以取得類別 cl,因此,除非打算將函數用作方法,否則請勿使用此樣式命名函數。

建議讀者參閱 R 語言定義,以更完整地討論此機制。


11 R 中的統計模型

此部分假設讀者對統計方法論有一定程度的熟悉度,特別是迴歸分析和變異數分析。稍後,我們會做出更具野心的假設,即讀者對廣義線性模型和非線性迴歸有一定程度的了解。

擬合統計模型的要求定義得相當完善,因此可以建構適用於廣泛問題的通用工具。

R 提供一組相互連鎖的設施,讓統計模型的擬合變得非常簡單。如同我們在引言中提到的,基本輸出是最小的,而且需要透過呼叫萃取器函數來請求詳細資料。


11.1 定義統計模型;公式

統計模型的範本是具有獨立同質變異數的線性迴歸模型

y_i = sum_{j=0}^p beta_j x_{ij} + e_i,     i = 1, ..., n,

其中 e_i 是 NID(0, sigma^2)。在矩陣術語中,這會寫成

y = X  beta + e

其中 y 是回應向量,X模型矩陣設計矩陣,並具有欄 x_0, x_1, ..., x_p,即決定變數。通常 x_0 會是一欄個位數,定義一個 截距 項。

範例

在提供正式規格之前,幾個範例可能會很有用地設定圖片。

假設 yxx0x1x2、… 是數值變數,X 是矩陣,而 ABC、… 是因子。以下左側的公式指定右側所述的統計模型。

y ~ x
y ~ 1 + x

兩者都暗示 yx 上的相同簡單線性迴歸模型。第一個有隱含的截距項,而第二個有明確的截距項。

y ~ 0 + x
y ~ -1 + x
y ~ x - 1

yx 上的簡單線性迴歸,通過原點(即沒有截距項)。

log(y) ~ x1 + x2

轉換變數 log(y) 在 x1x2 上的多重迴歸(有隱含的截距項)。

y ~ poly(x,2)
y ~ 1 + x + I(x^2)

yx 上的 2 次多項式迴歸。第一個形式使用正交多項式,而第二個形式使用明確的冪次作為基礎。

y ~ X + poly(x,2)

多重迴歸 y,其模型矩陣由矩陣 X 以及 x 中的 2 次多項式項組成。

y ~ A

y 的單一分類變異數分析模型,其類別由 A 決定。

y ~ A + x

y 的單一分類共變異數分析模型,其類別由 A 決定,且有協變數 x

y ~ A*B
y ~ A + B + A:B
y ~ B %in% A
y ~ A/B

yAB 上的兩因子非加成模型。前兩個指定相同的交叉分類,而後兩個指定相同的巢狀分類。抽象來說,所有四個都指定相同的模型子空間。

y ~ (A + B + C)^2
y ~ A*B*C - A:B:C

三因素實驗,但模型僅包含主效應和兩個因子交互作用。兩個公式指定相同的模型。

y ~ A * x
y ~ A/x
y ~ A/(1 + x) - 1

y 的層級中,使用不同的編碼,對x 進行獨立的簡單線性迴歸模型。最後一個形式產生與A 中層級一樣多的不同截距和斜率的明確估計。

y ~ A*B + Error(C)

一個具有兩個處理因素AB 的實驗,以及由因子C 確定的誤差階層。例如,一個分割區塊實驗,其中全區塊(因此也包括子區塊)由因子C 確定。

運算子 ~ 用於在 R 中定義模型公式。對於普通線性模型,形式為

response ~ op_1 term_1 op_2 term_2 op_3 term_3 ...

其中

response

是一個向量或矩陣(或評估為向量或矩陣的表達式),定義回應變數。

op_i

是一個運算子,為 +-,表示在模型中包含或排除一個術語(第一個是可選的)。

term_i

  • 一個向量或矩陣表達式,或 1
  • 一個因子,或
  • 一個公式表達式,由通過公式運算子連接的因子、向量或矩陣組成。

在所有情況下,每個術語都定義了一組要添加到模型矩陣或從模型矩陣中移除的列。一個 1 代表一個截距列,並且在預設情況下包含在模型矩陣中,除非明確移除。

公式運算子 的效果類似於 Glim 和 Genstat 等程式所使用的 Wilkinson 和 Rogers 符號。一個不可避免的變更為運算子「.」變為「:」,因為句點是 R 中的有效名稱字元。

符號總結如下(根據 Chambers & Hastie,1992 年,第 29 頁)

Y ~ M

Y 被建模為 M

M_1 + M_2

包含 M_1M_2

M_1 - M_2

包含 M_1,略過 M_2 的項目。

M_1 : M_2

M_1M_2 的張量積。如果兩個項目都是因子,則為「子類別」因子。

M_1 %in% M_2

類似於 M_1:M_2,但編碼不同。

M_1 * M_2

M_1 + M_2 + M_1:M_2.

M_1 / M_2

M_1 + M_2 %in% M_1.

M^n

M 中的所有項目,以及最高階數為 n 的「交互作用」

I(M)

隔離 M。在 M 內部,所有運算子都有其正常的算術意義,且該項目出現在模型矩陣中。

請注意,通常用於函數參數的括號內,所有運算子都具有其正常的算術意義。函數 I() 是一個恆等函數,用於允許使用算術運算子定義模型公式中的術語。

特別要注意,模型公式指定 模型矩陣的欄,參數的規格是隱含的。這與其他情況不同,例如在指定非線性模型時。


11.1.1 對比

我們至少需要一些概念,了解模型公式如何指定模型矩陣的欄。如果我們有連續變數,這很容易,因為每個變數提供模型矩陣的一欄(如果模型中包含截距,則截距將提供一欄個位數)。

k 水準因子 A 呢?對於無序因子和有序因子,答案不同。對於 無序 因子,會為第二個、…、k 個因子水準的指標產生 k - 1 欄。(因此,隱含參數化是將每個水準的反應與第一個水準的反應進行對比。)對於 有序 因子,k - 1 欄是 1, ..., k 上的正交多項式,省略常數項。

儘管答案已經很複雜,但這還不是全部。首先,如果在包含因子項的模型中省略截距,則第一個此類項會編碼成 k 欄,提供所有水準的指標。其次,整個行為都可以通過 contrastsoptions 設定來改變。R 中的預設設定是

options(contrasts = c("contr.treatment", "contr.poly"))

提及這一點的主要原因在於 R 和 S 對無序因子有不同的預設值,S 使用 Helmert 對比。因此,如果您需要將您的結果與使用 S-PLUS 的教科書或論文進行比較,您需要設定

options(contrasts = c("contr.helmert", "contr.poly"))

這是故意的差異,因為處理對比(R 的預設值)被認為較容易讓新手解讀。

我們還沒有完成,因為可以使用函數 contrastsC 為模型中的每個術語設定要使用的對比方案。

我們尚未考慮交互作用項:這些項會產生為其組成項引入的欄位的乘積。

儘管細節很複雜,但 R 中的模型公式通常會產生專家統計學家預期的模型,前提是保留邊際性。例如,擬合一個具有交互作用但沒有對應主效應的模型通常會導致令人驚訝的結果,並且僅適用於專家。


11.2 線性模型

用於擬合普通多元模型的基本函數為 lm(),呼叫的簡化版本如下:

> fitted.model <- lm(formula, data = data.frame)

例如

> fm2 <- lm(y ~ x1 + x2, data = production)

將擬合一個 yx1x2 的多元迴歸模型(具有隱含的截距項)。

重要(但技術上為選用)參數 data = production 指定任何建構模型所需的變數應優先來自 production 資料框無論資料框 production 是否已附加在搜尋路徑上,皆適用


11.3 萃取模型資訊的通用函數

lm() 的值是已套裝好的模型物件;技術上來說是 "lm" 類別的結果清單。然後,可以使用針對 "lm" 類別物件調整的通用函數來顯示、萃取、繪製等已套裝好模型的資訊。這些函數包括

add1    deviance   formula      predict  step
alias   drop1      kappa        print    summary
anova   effects    labels       proj     vcov
coef    family     plot         residuals

以下是對最常使用的函數的簡要說明。

anova(object_1, object_2)

將子模型與外部模型進行比較,並產生變異數分析表。

coef(object)

萃取迴歸係數(矩陣)。

長格式:coefficients(object)

deviance(object)

殘差平方和,適當加權。

formula(object)

萃取模型公式。

plot(object)

產生四個圖形,顯示殘差、擬合值和一些診斷。

predict(object, newdata=data.frame)

所提供的資料框必須具有與原始資料相同的標籤所指定的變數。值是對應於 data.frame 中決定變數值的預測值向量或矩陣。

print(object)

列印物件的簡潔版本。最常隱含地使用。

residuals(object)

萃取(矩陣的)殘差,適當地加權。

簡寫:resid(object)

step(object)

透過新增或刪除項目並保留層級來選擇合適的模型。會傳回在逐步搜尋中發現的 AIC(赤池資訊準則)值最小的模型。

summary(object)

列印迴歸分析結果的綜合摘要。

vcov(object)

傳回已擬合模型物件的主要參數的變異共變異數矩陣。


11.4 變異數分析與模型比較

模型擬合函數 aov(formula, data=data.frame) 運作在最簡單的層級上,與函數 lm() 非常類似,而且 用於萃取模型資訊的通用函數 表格中所列出的多數通用函數都適用。

應注意的是,除了 aov() 允許分析具有多重誤差層的模型,例如分割區塊實驗,或平衡不完全區塊設計,並復原區塊間資訊。模型公式

response ~ mean.formula + Error(strata.formula)

指定一個多層實驗,其中誤差層由 strata.formula 定義。在最簡單的情況下,strata.formula 僅僅是一個因子,當它定義一個二層實驗時,也就是在因子的層級之間和層級內。

例如,對於所有決定變數因子,例如

> fm <- aov(yield ~ v + n*p*k + Error(farms/blocks), data=farm.data)

中的模型公式通常用於描述具有平均模型 v + n*p*k 和三個誤差層的實驗,也就是「農場之間」、「農場內,區塊之間」和「區塊內」。


11.4.1 ANOVA 表格

另請注意,變異數分析表(或表格)是針對一系列擬合模型。顯示的平方和是殘差平方和的減少,這是由於在模型中包含該項在序列中的該位置所致。因此,只有對於正交實驗,包含順序才會無關緊要。

對於多層實驗,程序首先是將響應投影到誤差層,再次按順序,並將平均模型擬合到每個投影。有關更多詳細資訊,請參閱 Chambers & Hastie (1992)。

預設完整 ANOVA 表格更靈活的替代方案是使用 anova() 函數直接比較兩個或多個模型。

> anova(fitted.model.1, fitted.model.2, ...)

然後,顯示是一個 ANOVA 表格,顯示按順序擬合時擬合模型之間的差異。當然,要比較的擬合模型通常是階層順序。這並不會提供與預設不同的資訊,而是讓它更容易理解和控制。


11.5 更新擬合模型

update() 函數在很大程度上是一個便利函數,它允許擬合一個模型,該模型與先前擬合的模型不同,通常僅透過幾個額外的或移除的項。它的形式是

> new.model <- update(old.model, new.formula)

new.formula 中,由一個句點組成的特殊名稱「.,只能用來代表「舊模型公式的對應部分」。例如,

> fm05 <- lm(y ~ x1 + x2 + x3 + x4 + x5, data = production)
> fm6  <- update(fm05, . ~ . + x6)
> smf6 <- update(fm6, sqrt(.) ~ .)

將會調整一個五個變數的多元迴歸,變數(假設)來自資料框 production,調整一個包含第六個迴歸變數的額外模型,並調整一個模型變異,其中回應套用了平方根轉換。

特別注意,如果 data= 參數指定在模型調整函數的原始呼叫中,此資訊會透過調整好的模型物件傳遞到 update() 及其相關函數。

名稱「.」也可以用在其他情境中,但意義略有不同。例如

> fmfull <- lm(y ~ . , data = production)

將會調整一個模型,其回應為 y,迴歸變數為資料框 production 中所有其他變數

用於探索模型遞增序列的其他函數為 add1()drop1()step() 這些名稱清楚地提示了其目的,但如需完整詳細資料,請參閱線上說明。


11.6 廣義線性模型

廣義線性模型是線性模型的發展,用於以一種簡潔直接的方式容納非常態的反應分佈和線性轉換。廣義線性模型可用以下假設序列來描述

  • 有一個感興趣的反應,y,和刺激變數 x_1、x_2、…,其值會影響反應的分配。
  • 刺激變數僅透過單一線性函數影響 y 的分配。此線性函數稱為線性預測器,通常寫作
    eta = beta_1 x_1 + beta_2 x_2 + ... + beta_p x_p,
    

    因此,當且僅當 beta_i 為零時,x_i 就不會影響 y 的分配。

  • y 的分配形式為
    f_Y(y; mu, phi)
      = exp((A/phi) * (y lambda(mu) - gamma(lambda(mu))) + tau(y, phi))
    

    其中 phi 是尺度參數(可能已知),並且對於所有觀測值都是常數,A 表示先驗權重,假設已知但可能隨著觀測值而變化,而 $\mu$ 是 y 的平均值。因此假設 y 的分配是由其平均值和可能的尺度參數所決定的。

  • 平均值 mu 是線性預測器的平滑可逆函數
    mu = m(eta),    eta = m^{-1}(mu) = ell(mu)
    

    而此反函數 ell() 稱為連結函數

這些假設足夠寬鬆,可以涵蓋統計實務中各種有用的模型,但又足夠嚴謹,可以發展出統一的估計和推論方法,至少近似如此。讀者可以參閱任何一本現行的相關參考書,例如 McCullagh & Nelder (1989) 或 Dobson (1990),以取得完整的詳細資料。


11.6.1 族

R 中提供的工具處理的廣義線性模型類別包括 gaussianbinomialpoissoninverse gaussiangamma 反應分佈,以及反應分佈未明確指定的 quasi-likelihood 模型。在後一種情況下,變異數函數 必須指定為平均數的函數,但在其他情況下,此函數由反應分佈暗示。

每個反應分佈都允許多種連結函數,用於將平均數與線性預測值連接起來。自動可用的函數顯示在下列表格中

族名稱連結函數
二項logitprobitlogcloglog
gaussianidentityloginverse
Gammaidentityinverselog
inverse.gaussian1/mu^2identityinverselog
poissonidentitylogsqrt
quasilogitprobitcloglogidentityinverselog1/mu^2sqrt

回應分佈、連結函數和執行建模練習所需的各種其他資訊的組合稱為廣義線性模型的


11.6.2 glm() 函數

由於回應的分佈僅透過單一的線性函數取決於刺激變數,因此仍然可以使用與線性模型相同的機制來指定廣義模型的線性部分。族必須以不同的方式指定。

用於擬合廣義線性模型的 R 函數為 glm(),其使用以下形式:

> fitted.model <- glm(formula, family=family.generator, data=data.frame)

唯一的特點是 family.generator,它是用來描述族的工具。它是用來產生函數和表達式清單的函數名稱,這些函數和表達式共同定義和控制模型和估計程序。儘管這乍看之下似乎有點複雜,但它的使用非常簡單。

標準、提供的家族產生器的名稱在 家族 表格中的「家族名稱」下提供。如果有多個連結可以選擇,連結的名稱也可以用括號表示,作為參數,與家族名稱一起提供。對於 quasi 家族,變異函數也可以用這種方式指定。

一些範例可以讓這個過程更清楚。

gaussian 家族

例如這樣的呼叫

> fm <- glm(y ~ x1 + x2, family = gaussian, data = sales)

會得到與

> fm <- lm(y ~ x1+x2, data=sales)

相同的結果,但效率低很多。請注意,gaussian 家族並未自動提供連結選項,因此不允許參數。如果某個問題需要具有非標準連結的 gaussian 家族,通常可以使用 quasi 家族來達成,我們稍後會看到。

binomial 家族

考慮 Silvey (1970) 中一個小型的人工範例。

在愛琴海的 Kalythos 島上,男性居民會罹患一種先天性眼疾,其影響會隨著年齡增長而加劇。對不同年齡的島民男性進行失明測試,並記錄結果。資料如下所示

年齡2035455570
受測人數5050505050
失明人數 617263744

我們考慮的問題是,針對這些資料擬合邏輯迴歸和 probit 模型,並估計每個模型的 LD50,也就是男性居民失明機率為 50% 的年齡。

如果 y 是年齡 x 時失明的人數,n 是受測人數,則這兩個模型的型式為 y ~ B(n, F(beta_0 + beta_1 x)),其中對於 probit 情況,F(z) = Phi(z) 是標準常態分配函數,在 logit 情況(預設)下,F(z) = e^z/(1+e^z)。在這兩種情況下,LD50 為 LD50 = - beta_0/beta_1,也就是分配函數的參數為零的點。

第一步是將資料設定為資料框

> kalythos <- data.frame(x = c(20,35,45,55,70), n = rep(50,5),
                         y = c(6,17,26,37,44))

若要使用 glm() 擬合二項式模型,則回應有下列三種可能性

  • 如果回應是 向量,則假設它包含 二元 資料,因此必須是 0/1 向量。
  • 如果回應是 兩欄矩陣,則假設第一欄包含試驗的成功次數,而第二欄包含失敗次數。
  • 如果回應是 因子,則其第一個層級視為失敗 (0),而所有其他層級視為「成功」 (1)。

在這裡,我們需要第二個慣例,因此我們在資料框中新增一個矩陣

> kalythos$Ymat <- cbind(kalythos$y, kalythos$n - kalythos$y)

我們使用下列方式擬合模型

> fmp <- glm(Ymat ~ x, family = binomial(link=probit), data = kalythos)
> fml <- glm(Ymat ~ x, family = binomial, data = kalythos)

由於 logit 連結是預設值,因此可以在第二次呼叫時省略參數。若要查看每個擬合的結果,我們可以使用

> summary(fmp)
> summary(fml)

兩個模型都擬合得很好 (太好了)。若要找出 LD50 估計值,我們可以使用一個簡單函數

> ld50 <- function(b) -b[1]/b[2]
> ldp <- ld50(coef(fmp)); ldl <- ld50(coef(fml)); c(ldp, ldl)

從此資料中得到的實際估計值分別為 43.663 年和 43.601 年。

泊松模型

對於泊松族,預設連結是 log,在實務上,此族的主要用途是將替代泊松對數線性模型擬合到頻率資料,其實際分佈通常是多項式。這是一個龐大且重要的主題,我們在此不予深入探討。它甚至構成了非高斯廣義模型整體使用的一大部分。

偶爾會在實務中出現真正的泊松資料,過去通常在對數或平方根轉換後將其分析為高斯資料。作為後者的優雅替代方案,泊松廣義線性模型可以像以下範例中一樣進行擬合

> fmod <- glm(y ~ A + B + x, family = poisson(link=sqrt),
              data = worm.counts)

準似然模型

對於所有族群,回應的變異會取決於平均數,並將規模參數作為乘數。變異對平均數的依賴形式是回應分佈的特徵;例如,對於泊松分佈 Var(y) = mu。

對於準似然估計和推論,未指定精確的回應分佈,而僅指定連結函數和變異函數的形式,因為它取決於平均數。由於準似然估計使用與高斯分佈形式相同的技術,因此,此族群提供了一個擬合具有非標準連結函數或變異函數的高斯模型的方法,順便一提。

例如,考慮擬合非線性迴歸 y = theta_1 z_1 / (z_2 - theta_2) + e,也可以寫成 y = 1 / (beta_1 x_1 + beta_2 x_2) + e,其中 x_1 = z_2/z_1、x_2 = -1/z_1、beta_1 = 1/theta_1 和 beta_2 = theta_2/theta_1。假設設定一個合適的資料框,我們可以將此非線性迴歸擬合為

> nlfit <- glm(y ~ x1 + x2 - 1,
               family = quasi(link=inverse, variance=constant),
               data = biochem)

如有需要,請參閱手冊和說明文件以取得更多資訊。


11.7 非線性最小平方和最大似然模型

某些非線性模型形式可透過廣義線性模型 (glm()) 擬合。但在大多數情況下,我們必須將非線性曲線擬合問題視為非線性最佳化問題之一。R 的非線性最佳化常式為 optim()nlm()nlminb() 我們尋找可將某些不適度指標最小化的參數值,而它們會透過反覆嘗試各種參數值來執行此動作。舉例來說,與線性回歸不同,無法保證程序會收斂於滿意的估計值。所有方法都需要關於要嘗試的參數值之初始猜測,而收斂可能極度仰賴起始值的品質。


11.7.1 最小平方

擬合非線性模型的一種方式是將平方誤差總和 (SSE) 或殘差最小化。如果觀測誤差可能合理地來自常態分配,則此方法有意義。

以下是 Bates & Watts (1988) 第 51 頁的範例。資料為

> x <- c(0.02, 0.02, 0.06, 0.06, 0.11, 0.11, 0.22, 0.22, 0.56, 0.56,
         1.10, 1.10)
> y <- c(76, 47, 97, 107, 123, 139, 159, 152, 191, 201, 207, 200)

要最小化的擬合準則為

> fn <- function(p) sum((y - (p[1] * x)/(p[2] + x))^2)

為了執行擬合,我們需要參數的初始估計值。找出合理起始值的一種方式是繪製資料圖形、猜測一些參數值,並使用這些值疊加模型曲線。

> plot(x, y)
> xfit <- seq(.02, 1.1, .05)
> yfit <- 200 * xfit/(0.1 + xfit)
> lines(spline(xfit, yfit))

我們可以做得更好,但這些 200 和 0.1 的起始值看似足夠。現在執行擬合

> out <- nlm(fn, p = c(200, 0.1), hessian = TRUE)

在擬合後,out$minimum 是 SSE,而 out$estimate 是參數的最小平方估計值。若要取得估計值的近似標準誤差 (SE),我們會執行下列動作

> sqrt(diag(2*out$minimum/(length(y) - 2) * solve(out$hessian)))

上述列中減去的 2 代表參數的數量。95% 信賴區間會是參數估計值 +/- 1.96 SE。我們可以在新的繪圖上疊加最小平方擬合

> plot(x, y)
> xfit <- seq(.02, 1.1, .05)
> yfit <- 212.68384222 * xfit/(0.06412146 + xfit)
> lines(spline(xfit, yfit))

標準套件 stats 提供更廣泛的設施,用於透過最小平方來擬合非線性模型。我們剛剛擬合的模型是 Michaelis-Menten 模型,因此我們可以使用

> df <- data.frame(x=x, y=y)
> fit <- nls(y ~ SSmicmen(x, Vm, K), df)
> fit
Nonlinear regression model
  model:  y ~ SSmicmen(x, Vm, K)
   data:  df
          Vm            K
212.68370711   0.06412123
 residual sum-of-squares:  1195.449
> summary(fit)

Formula: y ~ SSmicmen(x, Vm, K)

Parameters:
    Estimate Std. Error t value Pr(>|t|)
Vm 2.127e+02  6.947e+00  30.615 3.24e-11
K  6.412e-02  8.281e-03   7.743 1.57e-05

Residual standard error: 10.93 on 10 degrees of freedom

Correlation of Parameter Estimates:
      Vm
K 0.7651

11.7.2 最大似然

最大似然是非線性模型擬合方法,即使誤差不為常態,也能套用。此方法會找出使對數似然值最大化,或等效地使負對數似然值最小化的參數值。以下是一個取自 Dobson (1990) 第 108-111 頁的範例。此範例會將邏輯模型擬合至劑量反應資料,顯然也能透過 glm() 進行擬合。資料如下

> x <- c(1.6907, 1.7242, 1.7552, 1.7842, 1.8113,
         1.8369, 1.8610, 1.8839)
> y <- c( 6, 13, 18, 28, 52, 53, 61, 60)
> n <- c(59, 60, 62, 56, 63, 59, 62, 60)

要最小化的負對數似然值為

> fn <- function(p)
   sum( - (y*(p[1]+p[2]*x) - n*log(1+exp(p[1]+p[2]*x))
           + log(choose(n, y)) ))

我們挑選合理的起始值並執行擬合

> out <- nlm(fn, p = c(-50,20), hessian = TRUE)

在擬合後,out$minimum 是負對數似然值,而 out$estimate 是參數的最大似然估計值。若要取得估計值的近似 SE,我們會執行下列動作

> sqrt(diag(solve(out$hessian)))

95% 信賴區間將是參數估計值 +/- 1.96 SE。


11.8 一些非標準模型

我們以簡要說明 R 中可供特殊迴歸和資料分析問題使用的其他一些功能來結束本章。

  • 混合模型。建議的 nlme 套件提供函數 lme()nlme() ,用於線性和非線性混合效果模型,也就是其中一些係數對應於隨機效果的線性和非線性迴歸。這些函數大量使用公式來指定模型。
  • 局部近似迴歸。 loess() 函數使用局部加權迴歸來擬合非參數迴歸。此類迴歸對於強調雜亂資料中的趨勢或資料簡約很有用,可深入了解大型資料集。

    函數 loess 位於標準套件 stats 中,以及用於投影追求迴歸的程式碼。

  • 穩健迴歸。有幾個函數可供以對極端異常值具有抵抗力的方式來擬合迴歸模型。建議套件 MASS 中的函數 lqs 提供了高度抵抗擬合的最新演算法。較不抵抗但統計上更有效率的方法可在套件中取得,例如套件 MASS 中的函數 rlm
  • 加法模型。此技術旨在從決定變數的平滑加法函數中建構迴歸函數,通常每個決定變數一個。套件 acepack 中的函數 avasace ,以及套件 mda 中的函數 brutomars 提供了 R 使用者貢獻套件中這些技術的一些範例。延伸是 廣義加法模型,在使用者貢獻套件 gammgcv 中實作。
  • 樹狀模型。樹狀模型並非尋求明確的全球線性模型以進行預測或詮釋,而是尋求在決定變數的臨界點遞迴地將資料二分,以最終將資料分割成在內部儘可能同質,在之間儘可能異質的群組。結果通常會產生其他資料分析方法傾向於無法產生的見解。

    模型再次以普通線性模型形式指定。模型擬合函數為 tree() 但許多其他通用函數(例如 plot()text())都非常適合以圖形方式顯示基於樹的模型擬合的結果。

    樹模型可在 R via 使用者貢獻的套件 rparttree 中取得。


12 圖形程序

圖形功能是 R 環境中重要且用途廣泛的組成部分。可以使用這些功能顯示各種統計圖形,也可以建立全新類型的圖形。

圖形功能可以在互動模式和批次模式下使用,但在大多數情況下,互動使用更有效率。互動使用也很容易,因為 R 在啟動時會啟動一個圖形 裝置驅動程式,為互動式圖形顯示開啟一個特殊的 圖形視窗。雖然這會自動執行,但可能需要知道在 UNIX 下使用的指令為 X11(),在 Windows 下為 windows(),在 macOS 下為 quartz()。可以使用 dev.new() 隨時開啟新的裝置。

一旦裝置驅動程式執行中,R 繪圖指令可用於產生各種圖形顯示,並建立全新類型的顯示。

繪圖指令分為三組基本群組

此外,R 維護一個圖形參數清單,可用於自訂繪圖。

本手冊僅說明所謂的「基礎」圖形。套件中的獨立圖形子系統grid 與基礎共存,功能更強大,但較難使用。建議使用套件lattice,其建立於grid 上,並提供產生多面板繪圖的方式,類似於 S 中的Trellis 系統。


12.1 高階繪圖指令

高階繪圖函式用於產生傳遞給函式引數的資料的完整繪圖。在適當的情況下,會自動產生座標軸、標籤和標題(除非您另有要求)。高階繪圖指令總是會開始新的繪圖,必要時會清除目前的繪圖。


12.1.1 plot() 函式

R 中最常使用的繪圖函式之一是 plot() 函式。這是一個泛型函式:所產生的繪圖類型取決於第一個引數的類型或類別

plot(x, y)
plot(xy)

如果 xy 是向量,plot(x, y) 會產生 yx 的散佈圖。也可以透過提供一個引數(第二個形式)來產生相同的效果,這個引數可以是包含兩個元素 xy 的清單,或是一個兩欄的矩陣。

plot(x)

如果 x 是時間序列,這會產生時間序列繪圖。如果 x 是數字向量,它會產生向量中數值對應於向量中索引的繪圖。如果 x 是複數向量,它會產生向量元素的虛部對實部的繪圖。

plot(f)
plot(f, y)

f 是因子物件,y 是數值向量。第一個形式產生 f 的長條圖;第二個形式產生 f 各個層級的 y 箱型圖。

plot(df)
plot(~ expr)
plot(y ~ expr)

df 是資料框,y 是任何物件,expr 是由「+」分隔的物件名稱清單(例如 a + b + c)。前兩個形式產生資料框中變數的分配圖(第一個形式)或多個命名物件的分配圖(第二個形式)。第三個形式依序將 y 繪製在 expr 中命名的每個物件上。


12.1.2 顯示多變量資料

R 提供兩個非常有用的函數來表示多變量資料。如果 X 是數值矩陣或資料框,則指令

> pairs(X)

會產生由 X 的欄位定義的變數的成對散佈圖矩陣,也就是說,X 的每個欄位會繪製在 X 的每個其他欄位上,而產生的 n(n-1) 個圖形會排列在矩陣中,而矩陣列和欄的繪圖比例會保持不變。

當涉及三或四個變數時,coplot 可能會更具啟發性。如果 ab 是數值向量,而 c 是數值向量或因子物件(所有長度相同),則指令

> coplot(a ~ b | c)

產生多個 a 對應 b 的散佈圖,針對 c 的特定值。如果 c 是個因子,這表示 a 會針對 c 的每個層級繪製對應 b 的圖形。當 c 是個數字時,會將其分成多個條件區間,並針對每個區間繪製 c 在區間內的數值對應 ab 的圖形。區間的數量和位置可以用 given.values= 參數來控制 coplot()co.intervals() 函式可用於選擇區間。你也可以使用兩個給定變數,搭配類似這樣的指令

> coplot(a ~ b | c + d)

產生 a 對應 b 的散佈圖,針對 cd 的每個聯合條件區間。

函式 coplot()pairs() 都有一個 panel= 參數,可用於自訂每個面板中顯示的圖形類型。預設值是 points(),用於產生散佈圖,但你可以提供其他低階繪圖函式(輸入兩個向量 xy)作為 panel= 的值,就能產生任何你想要的圖形類型。一個對共變數圖有用的範例面板函式是 panel.smooth()


12.1.3 顯示圖形

其他高階繪圖函式會產生不同類型的圖形。以下是一些範例

qqnorm(x)
qqline(x)
qqplot(x, y)

分佈比較圖形。第一個形式將數值向量 x 繪製在預期的常態順序分數上(常態分數圖形),而第二個形式會在這樣的圖形中加入一條直線,透過繪製一條線穿過分佈和資料的四分位數。第三個形式將 x 的分位數繪製在 y 的分位數上,以比較它們各自的分布。

hist(x)
hist(x, nclass=n)
hist(x, breaks=b, …)

產生數值向量 x 的直方圖。通常會選擇合理的類別數,但可以使用 nclass= 參數提供建議。或者,可以使用 breaks= 參數明確指定中斷點。如果提供了 probability=TRUE 參數,則長條形會表示相對頻率除以 bin 寬度,而不是計數。

dotchart(x, …)

建立 x 中資料的點狀圖。在點狀圖中,y 軸標示 x 中的資料,而 x 軸則表示其值。例如,它允許輕鬆視覺選擇值位於指定範圍內的所有資料項目。

image(x, y, z, …)
contour(x, y, z, …)
persp(x, y, z, …)

三個變數的圖形。 image 圖形使用不同的顏色繪製矩形網格來表示 z 的值,contour 圖形繪製等高線來表示 z 的值,而 persp 圖形繪製 3D 曲面。


12.1.4 傳遞給高級繪圖函數的參數

傳遞給高級繪圖函數的參數如下

add=TRUE

強制函數作為低級繪圖函數,將圖形疊加在目前的圖形上(僅限部分函數)。

axes=FALSE

取消產生座標軸,這對於使用 axis() 函數加入自訂座標軸時很有用。預設值 axes=TRUE 表示包含座標軸。

log="x"
log="y"
log="xy"

使 xy 或兩個座標軸都變成對數座標軸。這適用於許多,但並非所有類型的圖形。

type=

type= 參數控制產生的圖形類型,如下

type="p"

繪製個別點(預設值)

type="l"

繪製線條

type="b"

繪製以線條連接的點(both

type="o"

繪製疊加在線條上的點

type="h"

繪製從點到零軸的垂直線條(high-density

type="s"
type="S"

階梯函數圖形。在第一個形式中,垂直線條的頂端定義點;在第二個形式中,底部定義點。

type="n"

完全不繪製圖形。但是,座標軸仍然會繪製(預設值),且會根據資料設定座標系統。非常適合使用後續低級繪圖函數建立圖形。

xlab=字串
ylab=字串

xy 軸的軸標籤。使用這些參數來變更預設標籤,通常是呼叫高階繪圖函數時所使用的物件名稱。

main=字串

圖形標題,置於繪圖上方,以較大的字型顯示。

sub=字串

副標題,置於 x 軸正下方,以較小的字型顯示。


12.2 低階繪圖命令

有時高階繪圖函數無法產生您想要的繪圖類型。在這種情況下,可以使用低階繪圖命令將額外資訊(例如點、線或文字)新增到目前的繪圖中。

一些較有用的低階繪圖函數為

points(x, y)
lines(x, y)

將點或連接線新增到目前的繪圖中。plot()type= 參數也可以傳遞給這些函數(並且預設為 points()"p"lines()"l")。

text(x, y, labels, …)

在由 x, y 指定的點上新增文字至繪圖。通常 labels 是整數或字元向量,在此情況下 labels[i] 會繪製於點 (x[i], y[i])。預設值為 1:length(x)

注意:此函數通常用於下列順序

> plot(x, y, type="n"); text(x, y, names)

圖形參數 type="n" 會抑制點,但會設定軸,而 text() 函數會提供特殊字元,如字元向量 names 所指定的點。

abline(a, b)
abline(h=y)
abline(v=x)
abline(lm.obj)

將斜率為 b、截距為 a 的線新增至目前的繪圖。可以使用 h=y 來指定橫線在繪圖中高度的 y 座標,而 v=x 則用於指定垂直線的 x 座標。此外,lm.obj 可以是長度為 2 的 coefficients 組件清單(例如模型擬合函數的結果),依序視為截距和斜率。

polygon(x, y, …)

繪製由 (x, y) 中的順序頂點定義的多邊形,並(選擇性地)用網格線陰影或填滿,如果圖形裝置允許填滿圖形。

legend(x, y, legend, …)

在指定位置新增一個圖例到目前的繪圖。繪圖字元、線條樣式、顏色等,會與字元向量 legend 中的標籤相符。至少要提供另一個參數 v(一個與 legend 長度相同的向量),其中包含繪圖單位的對應值,如下所示

legend( , fill=v)

填滿方塊的顏色

legend( , col=v)

繪製點或線條的顏色

legend( , lty=v)

線條樣式

legend( , lwd=v)

線條寬度

legend( , pch=v)

繪圖字元(字元向量)

title(main, sub)

在目前繪圖的頂端新增一個標題 main,使用較大的字體,並(選擇性地)在底部新增一個較小的副標題 sub

axis(side, …)

在目前繪圖中新增一個座標軸,在第一個參數指定的側面(從底部開始順時針計算,為 1 至 4)。其他參數控制座標軸在繪圖中或繪圖旁的位置,以及刻度位置和標籤。在使用 axes=FALSE 參數呼叫 plot() 之後,可使用此函數新增自訂座標軸。

低階繪圖函數通常需要一些定位資訊(例如 xy 座標),以決定將新的繪圖元素置於何處。座標以 使用者座標 表示,這些座標由前一個高階圖形指令定義,並根據提供的資料選擇。

xy 參數為必要時,提供一個參數,其中包含名為 xy 的元素清單,也是足夠的。類似地,一個具有兩欄的矩陣也是有效的輸入。藉由這種方式,例如 locator()(見下文)等函數可用於互動式地指定繪圖上的位置。


12.2.1 數學註解

在某些情況下,在繪圖中加入數學符號和公式是有用的。這可以在 R 中藉由在 textmtextaxistitle 中指定一個表達式,而非字元字串來達成。例如,下列程式碼繪製二項機率函數的公式

> text(x, y, expression(paste(bgroup("(", atop(n, x), ")"), p^x, q^{n-x})))

更多資訊,包括功能的完整清單,可以使用下列命令從 R 中取得

> help(plotmath)
> example(plotmath)
> demo(plotmath)

12.2.2 Hershey 向量字型

在使用 textcontour 函數時,可以指定 Hershey 向量字型來呈現文字。使用 Hershey 字型的理由有三個

  • Hershey 字型可以產生更好的輸出,特別是在電腦螢幕上,用於旋轉和/或小文字。
  • Hershey 字型提供標準字型中可能沒有的特定符號。特別是,有十二生肖、製圖符號和天文符號。
  • Hershey 字型提供西里爾文和日文(假名和漢字)字元。

更多資訊,包括 Hershey 字元的表格,可以使用以下指令從 R 中取得

> help(Hershey)
> demo(Hershey)
> help(Japanese)
> demo(Japanese)

12.3 與圖形互動

R 也提供函數,允許使用者使用滑鼠從繪圖中擷取或新增資訊。最簡單的是 locator() 函數

locator(n, type)

等待使用者使用滑鼠左鍵在目前繪圖中選取位置。此動作會持續進行,直到選取到 n (預設為 512) 個點,或按壓其他滑鼠按鍵。 type 參數允許在選取的點上繪圖,其效果與高階繪圖指令相同;預設為不繪圖。 locator() 會傳回選取點的位置,作為具有兩個元件 xy 的清單。

locator() 通常在沒有參數的情況下呼叫。當難以事先計算圖形放置位置時,特別適用於互動式選取圖形元素(例如圖例或標籤)的位置。例如,若要將一些說明文字放置在偏遠點附近,則指令

> text(locator(1), "Outlier", adj=0)

可能會很有用。(如果目前裝置(例如 postscript)不支援互動式指標,則會忽略 locator()。)

identify(x, y, labels)

允許使用者使用滑鼠左鍵突顯由 xy 定義的任何點,方法是在附近繪製 labels 的對應元件(或如果沒有 labels,則繪製點的索引編號)。當按壓其他按鈕時,傳回選取點的索引。

有時我們想要辨識繪圖中的特定 ,而不是它們的位置。例如,我們可能希望使用者從圖形顯示中選取一些感興趣的觀察值,然後以某種方式操作該觀察值。假設兩個數字向量 xy 中有許多 (x, y) 座標,我們可以使用 identify() 函數,如下所示

> plot(x, y)
> identify(x, y)

函數 identify() 本身不執行繪圖,僅允許使用者移動滑鼠指標並在點附近按一下滑鼠左鍵。如果滑鼠指標附近有某個點,則會在附近標示其索引編號(亦即在 x/y 向量中的位置)。或者,您可以使用一些具有資訊性的字串(例如案例名稱)作為重點,方法是使用 identify()labels 參數,或使用 plot = FALSE 參數完全停用標示。當程序終止(見上文)時,identify() 會傳回所選點的索引;您可以使用這些索引從原始向量 xy 中擷取所選點。


12.4 使用圖形參數

在建立圖形時,特別是為了簡報或出版目的,R 的預設值並非總能產生完全符合需求的結果。不過,您可以使用圖形參數自訂顯示的幾乎每個面向。R 維護一個大型圖形參數清單,用來控制許多項目,例如線條樣式、色彩、圖形配置和文字對齊。每個圖形參數都有名稱(例如控制色彩的「col」)和值(例如色彩編號)。

每個活動裝置都維護一個獨立的圖形參數清單,每個裝置在初始化時都有一組預設參數。圖形參數可以透過兩種方式設定:永久設定,影響存取目前裝置的所有圖形函數;或暫時設定,僅影響單一圖形函數呼叫。


12.4.1 永久變更:par() 函數

par() 函數用於存取和修改目前圖形裝置的圖形參數清單。

par()

不帶參數時,傳回目前裝置所有圖形參數及其值的清單。

par(c("col", "lty"))

帶字元向量參數時,僅傳回指定的圖形參數(同樣以清單形式)。

par(col=4, lty=2)

帶命名參數(或單一清單參數)時,設定指定圖形參數的值,並傳回參數的原始值(以清單形式)。

使用 par() 函數設定圖形參數會永久變更參數的值,意即所有未來對圖形函數的呼叫(在目前裝置上)都會受到新值的影響。您可以將這種方式的圖形參數設定視為設定參數的「預設」值,所有圖形函數都會使用這些值,除非另有指定其他值。

請注意,對 par() 的呼叫總是會影響圖形參數的全球值,即使 par() 是從函數內部呼叫的。這通常是不希望出現的行為,一般而言,我們希望設定一些圖形參數,進行一些繪圖,然後還原原始值,以免影響使用者的 R 工作階段。您可以透過在進行變更時儲存 par() 的結果,並在繪圖完成時還原原始值,來還原初始值。

> oldpar <- par(col=4, lty=2)
  ... plotting commands ...
> par(oldpar)

若要儲存和還原所有可設定24圖形參數,請使用

> oldpar <- par(no.readonly=TRUE)
  ... plotting commands ...
> par(oldpar)

12.4.2 暫時變更:圖形函數的參數

圖形參數也可以傳遞給(幾乎)任何圖形函數作為命名參數。這與將參數傳遞給 par() 函數有相同的效果,但變更只會持續函數呼叫期間。例如

> plot(x, y, pch="+")

使用加號作為繪製字元產生散佈圖,而不會變更未來繪圖的預設繪製字元。

不幸的是,這沒有完全一致地實作,有時需要使用 par() 設定和重設圖形參數。


12.5 圖形參數清單

下列各節詳細說明許多常用的圖形參數。R 說明文件中的 par() 函數提供更簡潔的摘要;這提供了一個更詳細的替代方案。

圖形參數將以下列形式呈現

名稱=

參數效果的描述。 name 是參數的名稱,也就是在呼叫 par() 或繪圖函數時使用的引數名稱。 value 是設定參數時您可能會使用的典型值。

請注意, axes 不是繪圖參數,而是幾個 plot 方法的引數:請參閱 xaxtyaxt


12.5.1 圖形元素

R 繪圖由點、線、文字和多邊形(填滿區域)組成。有繪圖參數可以控制這些 圖形元素 的繪製方式,如下所示

pch="+"

用於繪製點的字元。預設值會隨著繪圖驅動程式而有所不同,但通常是圓形。繪製的點傾向於出現在適當位置的正上方或正下方,除非您使用 "." 作為繪製字元,這會產生置中的點。

pch=4

pch 指定為介於 0 到 25(含)之間的整數時,會產生一個專門的繪製符號。若要查看符號,請使用指令

> legend(locator(1), as.character(0:25), pch = 0:25)

21 到 25 的符號可能看起來與先前的符號重複,但可以用不同的方式著色:請參閱 points 和其範例的說明。

此外, pch 可以是字元或介於 32:255 範圍內的數字,代表目前字型中的字元。

lty=2

線條類型。並非所有圖形裝置都支援變更線條樣式(而且支援的裝置樣式也有所不同),但線條類型 1 永遠是實線,線條類型 0 永遠是隱形,線條類型 2 及其後續類型為點線或虛線,或兩者的某種組合。

lwd=2

線條寬度。線條的理想寬度,為「標準」線條寬度的倍數。會影響軸線以及使用 lines() 等函數繪製的線條。並非所有裝置都支援此功能,而且某些裝置對於可使用的寬度設有限制。

col=2

用於點、線條、文字、填滿區域和影像的顏色。目前色盤中的數字(請參閱 ?palette)或已命名的顏色。

col.axis
col.lab
col.main
col.sub

分別用於軸註解、xy 標籤、主標題和副標題的顏色。

font=2

用於指定文字字型的整數。裝置驅動程式會盡可能將 1 對應到一般文字、2 對應到粗體、3 對應到斜體、4 對應到粗斜體、5 對應到符號字型(包括希臘字母)。

font.axis
font.lab
font.main
font.sub

分別用於軸註解、xy 標籤、主標題和副標題的字型。

adj=-0.1

文字相對於繪製位置的對齊方式。 0 表示靠左對齊、1 表示靠右對齊、0.5 表示以繪製位置為中心水平置中。實際值為文字出現在繪製位置左方的比例,因此 -0.1 的值會在文字和繪製位置之間留下 10% 文字寬度的間隙。

cex=1.5

字元擴充。此值是文字字元(包括繪製字元)相對於預設文字大小的所需大小。

cex.axis
cex.lab
cex.main
cex.sub

分別用於軸註解、xy 標籤、主標題和副標題的字元擴充。


12.5.2 軸線和刻度

R 的許多高階繪圖都有軸線,您也可以使用低階 axis() 圖形函數自行建構軸線。軸線有三個主要組成部分:軸線(線條樣式由 lty 圖形參數控制)、刻度(標示軸線上的單位區隔)和刻度標籤(標示單位)。這些組成部分可以使用下列圖形參數自訂。

lab=c(5, 7, 12)

前兩個數字分別是 xy 軸上所需的刻度間隔數。第三個數字是軸標籤所需的長度(以字元為單位,包括小數點)。如果為此參數選擇過小的值,可能會導致所有刻度標籤都捨入為相同的數字!

las=1

軸標籤的方向。0 表示永遠與軸線平行,1 表示永遠水平,2 表示永遠垂直於軸線。

mgp=c(3, 1, 0)

軸元件位置。第一個元件是軸標籤到軸位置的距離,以文字行表示。第二個元件是到刻度標籤的距離,最後一個元件是軸位置到軸線的距離(通常為零)。正數測量繪圖區域外,負數測量繪圖區域內。

tck=0.01

刻度的長度,作為繪圖區域大小的比例。當 tck 很小(小於 0.5)時,xy 軸上的刻度會強制為相同大小。值 1 會產生網格線。負值會產生繪圖區域外的刻度。對於內部刻度,請使用 tck=0.01mgp=c(1,-1.5,0)

xaxs="r"
yaxs="i"

分別對應 xy 軸的軸樣式。對於樣式 "i"(內部)和 "r"(預設),刻度會永遠落在資料範圍內,但樣式 "r" 會在邊緣留一些小空間。


12.5.3 圖形邊界

R 中的單一繪圖稱為 figure,包含一個 繪圖區域,周圍有邊界(可能包含軸標籤、標題等),且(通常)由軸本身界定。

一個典型的圖形是

images/fig11

控制圖形配置的圖形參數包括

mai=c(1, 0.5, 0.5, 0)

底部、左邊、頂部和右邊邊界的寬度,單位為英吋。

mar=c(4, 2, 2, 1)

類似於 mai,但測量單位為文字行數。

marmai 是等效的,因為設定其中一個會變更另一個的值。此參數選擇的預設值通常過大;很少需要右邊界,如果沒有使用標題,則也不需要頂部邊界。底部和左邊界必須夠大,才能容納軸和刻度標籤。此外,預設值不考慮裝置表面的大小:例如,將 postscript() 驅動程式與 height=4 參數一起使用,將會產生一個約 50% 為邊界的圖形,除非明確設定 marmai。當使用多個圖形時(請參閱下方),邊界會縮小,但當多個圖形共用同一個頁面時,這可能還不夠。


12.5.4 多個圖形環境

R 允許您在單一頁面上建立 n 乘以 m 的圖形陣列。每個圖形都有自己的邊界,而且圖形陣列可以選擇用 外邊界 包圍,如下圖所示。

images/fig12

與多個圖形相關的圖形參數如下

mfcol=c(3, 2)
mfrow=c(2, 4)

設定多個圖形陣列的大小。第一個值是列數;第二個值是欄數。這兩個參數之間唯一的差別在於設定 mfcol 會導致圖形以欄位為單位填滿; mfrow 則以列為單位填滿。

圖中的配置可以透過設定 mfrow=c(3,2) 建立;圖形在繪製四個圖形後顯示頁面。

設定其中任何一個參數都可以縮小符號和文字的基本大小(由 par("cex") 和裝置的點大小控制)。在恰好有兩列和兩行的配置中,基本大小縮小 0.83 倍:如果列或欄有三個或更多,縮小倍率為 0.66。

mfg=c(2, 2, 3, 2)

在多個圖形環境中,目前圖形的位置。前兩個數字是目前圖形所在的列和欄;後兩個數字是多個圖形陣列中的列數和欄數。設定此參數可在陣列中的圖形之間跳躍。您甚至可以使用與同一頁面上大小不一的圖形的 實際 值不同的值作為最後兩個數字。

fig=c(4, 9, 1, 4)/10

目前圖形在頁面上的位置。值分別是左、右、下和上邊緣的位置,以從左下角測量的頁面百分比表示。範例值會是頁面右下角的圖形。設定此參數可在頁面內任意定位圖形。如果您想將圖形新增到目前頁面,請也使用 new=TRUE(與 S 不同)。

oma=c(2, 0, 3, 0)
omi=c(0, 0, 0.8, 0)

外側邊界的尺寸。就像 marmai,第一個以文字行測量,第二個以英吋測量,從底部邊界開始順時針測量。

外側邊界對於頁面標題等特別有用。文字可以使用 mtext() 函數加上引數 outer=TRUE 加入到外側邊界。不過,預設沒有外側邊界,所以您必須使用 omaomi 明確建立。

較複雜的多個圖形排列可以使用 split.screen()layout() 函數,以及 gridlattice 套件產生。


12.6 裝置驅動程式

R 可以產生幾乎任何類型顯示器或印表機裝置上(品質等級不同)的圖形。不過,在開始之前,R 需要知道它處理的是哪種類型的裝置。這會透過啟動一個裝置驅動程式來進行。裝置驅動程式的目的是將 R 的圖形指令(例如「畫一條線」)轉換成特定裝置可以理解的形式。

裝置驅動程式透過呼叫裝置驅動程式函數來啟動。每個裝置驅動程式都有其中一個函數:輸入 help(Devices) 以取得所有函數的清單。例如,發出指令

> postscript()

會導致所有未來的圖形輸出以 PostScript 格式傳送到印表機。一些常用的裝置驅動程式有

X11()

供 Unix 類似系統上的 X11 視窗系統使用

windows()

供 Windows 使用

quartz()

供 macOS 使用

postscript()

供列印在 PostScript 印表機上,或建立 PostScript 圖形檔案使用。

pdf()

產生 PDF 檔案,也可以包含在 PDF 檔案中。

png()

產生位元圖 PNG 檔案。(不一定隨時可用:請參閱其說明頁面。)

jpeg()

產生位元圖 JPEG 檔案,最適合用於 image 繪圖。(不一定隨時可用:請參閱其說明頁面。)

使用完裝置後,務必透過發出指令終止裝置驅動程式

> dev.off()

這可確保裝置乾淨地完成;例如,在硬拷貝裝置的情況下,這可確保每個頁面都已完成並已傳送到印表機。(這會在會話正常結束時自動發生。)


12.6.1 排版文件中的 PostScript 圖表

透過將 file 參數傳遞給 postscript() 裝置驅動程式函數,您可以將圖形儲存在您選擇的檔案中,採用 PostScript 格式。除非給定 horizontal=FALSE 參數,否則繪圖會採用橫向,而您可以使用 widthheight 參數控制圖形的大小(繪圖會適當地縮放以符合這些尺寸)。例如,指令

> postscript("file.ps", horizontal=FALSE, height=5, pointsize=10)

將產生一個包含五吋高圖形的 PostScript 程式碼檔案,或許可以包含在文件中。重要的是要注意,如果指令中命名的檔案已經存在,它將被覆寫。即使該檔案僅在同一個 R 會話中稍早建立,情況也是如此。

PostScript 輸出的許多用法將會是將圖形納入其他文件中。當產生封裝 PostScript 時,效果最佳:R 永遠產生相容的輸出,但僅在提供 onefile=FALSE 參數時標示輸出為相容。這種不尋常的標示法源自 S 相容性:它真正表示輸出將會是單一頁面(這是 EPSF 規格的一部分)。因此,要產生包含繪圖的繪圖,請使用類似於

> postscript("plot1.eps", horizontal=FALSE, onefile=FALSE,
             height=8, width=6, pointsize=10)

12.6.2 多個圖形裝置

在進階使用 R 時,同時使用多個圖形裝置通常很有用。當然,任何時候只有一個圖形裝置可以接受圖形指令,而這稱為目前裝置。當開啟多個裝置時,它們會形成一個編號順序,名稱會指出任何位置的裝置類型。

用於操作多個裝置的主要指令及其意義如下

X11()

[UNIX]

windows()
win.printer()
win.metafile()

[Windows]

quartz()

[macOS]

postscript()
pdf()
png()
jpeg()
tiff()
bitmap()

每次呼叫裝置驅動程式函數都會開啟一個新的圖形裝置,因此會將裝置清單擴充一個。此裝置會成為目前裝置,圖形輸出會傳送給此裝置。

dev.list()

傳回所有有效裝置的數量和名稱。清單中位置 1 的裝置永遠是空裝置,它完全不接受圖形指令。

dev.next()
dev.prev()

分別傳回目前裝置之後或之前的圖形裝置的數量和名稱。

dev.set(which=k)

可用於將目前的繪圖裝置變更為裝置清單中位置 k 的裝置。傳回裝置的編號和標籤。

dev.off(k)

終止裝置清單中點 k 的繪圖裝置。對於某些裝置,例如 postscript 裝置,這將立即列印檔案或正確完成檔案以供稍後列印,具體取決於裝置的啟動方式。

dev.copy(device, …, which=k)
dev.print(device, …, which=k)

製作裝置 k 的副本。這裡 device 是裝置函數,例如 postscript,如有需要,則使用「」指定的額外參數。 dev.print 類似,但複製的裝置會立即關閉,以便立即執行結束動作,例如列印紙本。

graphics.off()

終止清單中的所有繪圖裝置,空裝置除外。


12.7 動態圖形

R 沒有內建動態或互動圖形的相關功能,例如旋轉點雲或「刷選」(互動式突顯)點。然而,Swayne、Cook 和 Buja 的 GGobi 系統中提供了廣泛的動態圖形功能,可從下列網址取得:

http://ggobi.org/

且可透過套件 rggobi 從 R 存取,說明請見 http://ggobi.org/rggobi.html

此外,套件 rgl 提供與 3D 圖形互動的方式,例如曲面。


13 套件

所有 R 函數和資料集都儲存在 套件 中。只有在套件載入時,其內容才會可用。這樣做既能提高效率(完整清單會佔用更多記憶體,而且搜尋時間會比子集更長),也能協助套件開發人員,避免與其他程式碼名稱衝突。開發套件的程序說明請參閱 撰寫 R 擴充套件 中的 建立 R 套件。在此,我們將從使用者的角度來描述它們。

若要查看您的網站上安裝了哪些套件,請發出指令

> library()

不帶任何引數。若要載入特定套件(例如,包含 Davison & Hinkley (1997) 函數的 boot 套件),請使用類似下列的指令

> library(boot)

已連上網際網路的使用者可以使用 install.packages()update.packages() 函數(可透過 Windows 和 macOS GUI 中的 套件 功能表取得,請參閱 R 安裝與管理 中的 安裝套件)來安裝和更新套件。

若要查看目前載入的套件,請使用

> search()

以顯示搜尋清單。有些套件可能已載入,但未顯示在搜尋清單中(請參閱 命名空間):這些套件會包含在

> loadedNamespaces()

中顯示的清單中。若要查看已安裝套件中的所有可用說明主題清單,請使用

> help.start()

以啟動 HTML 說明系統,然後在 參考 區段中瀏覽套件清單。


13.1 標準套件

標準(或 基本)套件被視為 R 原始碼的一部分。它們包含讓 R 能運作的基本函數,以及本手冊中描述的資料集和標準統計和圖形函數。它們應該會自動出現在任何 R 安裝中。請參閱 R 常見問答集 中的 R 套件,以取得完整清單。


13.2 貢獻套件和 CRAN

有數千個貢獻套件可供 R 使用,由許多不同的作者撰寫。其中一些套件實作了專業的統計方法,其他則提供存取資料或硬體的方式,而另一些則設計為教科書的補充教材。有些(建議的套件)會與 R 的每個二進位套件一起發行。大部分套件都可以在 CRANhttps://CRAN.R-project.org/ 及其鏡像網站)和其他儲存庫(例如 Bioconductor,https://www.bioconductor.org/)下載。R 常見問答集包含 CRAN 套件在發行時的清單,但可用的套件集合會非常頻繁地變更。


13.3 名稱空間

套件有名稱空間,它有三個功能:允許套件撰寫者隱藏僅供內部使用的函式和資料,防止使用者(或其他套件撰寫者)選擇與套件中名稱衝突的名稱時函式中斷,以及提供一種在特定套件中參照物件的方式。

例如,t() 是 R 中的轉置函式,但使用者可以定義他們自己的函式,並將其命名為 t。名稱空間可防止使用者的定義優先,並中斷嘗試轉置矩陣的每個函式。

有兩個運算子可與名稱空間搭配使用。雙冒號運算子 :: 從特定名稱空間中選取定義。在上面的範例中,轉置函式會一直以 base::t 的形式提供,因為它是在 base 套件中定義的。只有從套件中匯出的函式才能用這種方式擷取。

三冒號運算子 ::: 可能會出現在 R 程式碼中的幾個地方:它的作用類似於雙冒號運算子,但也可以存取隱藏的物件。使用者比較可能會使用 getAnywhere() 函數,它會搜尋多個套件。

套件通常是相互依賴的,載入一個套件可能會導致自動載入其他套件。上面說明的冒號運算子也會導致自動載入相關的套件。當具有命名空間的套件自動載入時,它們不會新增到搜尋清單中。


14 作業系統功能

R 具有相當廣泛的功能,可以存取其上執行的作業系統:這允許將其用作指令碼語言,而 R 本身也會大量使用此功能,例如安裝套件。

由於 R 本身的指令碼需要在所有平台上執行,因此已投入大量心力,讓指令碼功能盡可能與平台無關。


14.1 檔案和目錄

有許多函數可以處理檔案和目錄。以下是幾個較常使用的函數的指標。

若要建立(空的)檔案或目錄,請使用 file.createdir.create。(這些類似於 POSIX 工具程式 touchmkdir。)有關 R 會話目錄中的暫時檔案和目錄,請參閱 tempfile

檔案可以透過 file.removeunlink 移除:後者可以移除目錄樹。

若要列出目錄,請使用 list.files(也可用於 dir)或 list.dirs。這些可以使用正規表示式來選取檔案:若要使用萬用字元選取,請使用 Sys.glob

檔案路徑的許多資訊(例如是否為檔案或目錄)都可以透過 file.info 找到。

有許多方法可以找出檔案是否「存在」(檔案可能存在於檔案系統中,但目前使用者無法看見)。有函式 file.existsfile.accessfile_test,其中包含此測試的各種版本:file_test 是 POSIX test 指令的版本,適用於熟悉 shell 指令碼的人。

函式 file.copy 是 POSIX 指令 cp 的 R 類比。

可以透過 file.choose 互動式地選取檔案:Windows 埠具有更多功能的函式 choose.fileschoose.dir,而 tcltk 套件中也有類似的函式:tk_choose.filestk_choose.dir

函式 file.showfile.edit 會以適當於 R 埠的方式顯示和編輯一個或多個檔案,如果正在使用主控台(例如 Windows 上的 RGui 或 macOS 上的 R.app),則會使用主控台的功能。

檔案系統中有些支援 連結:請參閱函式 file.linkSys.readlink


14.2 檔案路徑

除了少數例外,R 依賴底層作業系統函式來處理檔案路徑。有些面向會依作業系統而定,甚至會依作業系統版本而定。POSIX 標準規範作業系統應如何詮釋檔案路徑,許多 R 使用者假設作業系統符合 POSIX:但 Windows 沒有宣稱符合,其他作業系統可能也不完全符合。

以下是使用檔案路徑時遇到的部分問題。

  • POSIX 檔案系統區分大小寫,所以 foo.pngFoo.PNG 是不同的檔案。然而,Windows 和 macOS 的預設值是不區分大小寫,而 FAT 檔案系統(通常用於可移除式儲存裝置)通常不區分大小寫(而且所有檔案路徑可能會對應到小寫)。
  • 幾乎所有 Windows 作業系統服務都支援使用斜線或反斜線作為檔案路徑分隔符號,而 R 會將已知的例外轉換成 Windows 所需的形式。
  • 有尾斜線的檔案路徑行為會依作業系統而定。此類路徑在 Windows 中無效,不應預期會運作。POSIX-2008 要求此類路徑只能比對目錄,但較早的版本允許它們也比對檔案。因此,最好避免使用。
  • 檔案路徑中有多個斜線,例如 /abc//def,在 POSIX 檔案系統中是有效的,且會視為只有一個斜線。Windows 作業系統函式通常會接受它們。然而,開頭的雙斜線可能會有不同的意義。
  • Windows 的 UNC 檔案路徑(例如 \\server\dir1\dir2\file\\?\UNC\server\dir1\dir2\file)不受支援,但它們可能會在某些 R 函式中運作。POSIX 檔案系統允許特別處理開頭的雙斜線。
  • Windows 允許檔案路徑包含磁碟機和相對於磁碟機上目前目錄的路徑,例如 d:foo/bar 指的是 d:/a/b/c/foo/bar,如果 磁碟機 d: 上的目前目錄/a/b/c。這些路徑預期會運作,但使用絕對路徑較安全。

函式 basenamedirname 選擇檔案路徑的部分:從組成部分組裝檔案路徑的建議方式是 file.path。函式 pathexpand 執行「波浪號展開」,替換主目錄的值(目前使用者,以及可能是其他使用者的主目錄)。

在有連結的檔案系統上,一個檔案可以用許多檔案路徑來參考。函式 normalizePath 會找出正規的檔案路徑。

Windows 有短檔名(「8.3」)和長檔名的概念:normalizePath 會傳回使用長檔名的絕對路徑,而 shortPathName 會傳回使用短檔名的版本。後者不包含空白,並使用反斜線作為分隔符號,因此有時可用於從 R 匯出名稱。

檔案權限是相關的主題。R 支援所有者/群組/所有人的 POSIX 讀取/寫入/執行權限概念,但這可能只在檔案系統上獲得部分支援,因此例如在 Windows 上只會辨識唯讀檔案(對於執行 R 工作階段的帳戶)。存取控制清單 (ACL) 用於數個檔案系統,但沒有約定的標準,而 R 沒有控制它們的工具。使用 Sys.chmod 來變更權限。


14.3 系統指令

函式 systemsystem2 用於呼叫系統指令並選擇性地收集其輸出。 system2 稍微通用一些,但其主要優點是使用它可以更容易地撰寫跨平台程式碼。

system 在 Windows 上的行為與其他作業系統不同(因為同名的 API C 呼叫也會這樣做)。在其他地方,它會呼叫 shell 來執行指令:R 的 Windows 埠有一個函式 shell 來執行此操作。

若要找出作業系統是否包含某個指令,請使用 Sys.which,它會嘗試以跨平台的方式執行此操作(很遺憾,這不是標準的作業系統服務)。

函式 shQuote 會根據目前作業系統的指令需要,對檔案路徑加上引號。


14.4 壓縮與封存

最近版本的 R 具有廣泛的功能來讀取和寫入壓縮檔案,通常是透明的。在 R 中讀取檔案在很大程度上是由 連線 來完成的,而 file 函式用於開啟與檔案(或 URL)的連線,並且能夠從檔案的「魔術」標頭中識別所使用的壓縮方式。

支援最久的壓縮類型是 gzip 壓縮,它仍然是一個很好的通用折衷方案。也可以讀取由較早的 Unix compress 工具壓縮的檔案,但這些檔案正變得越來越少見。另外兩種形式的壓縮,即 bzip2xz 工具的壓縮也可用。這些通常可以達到更高的壓縮率(視檔案而定,高出許多),但代價是解壓縮速度較慢,壓縮速度也慢得多。

對於 xzlzma 壓縮有一些混淆(請參閱 https://en.wikipedia.org/wiki/Xzhttps://en.wikipedia.org/wiki/LZMA):R 可以讀取大多數版本壓縮的檔案。

檔案歸檔檔是包含檔案集合的單一檔案,最常見的是用於分發 R 套件的「tarball」和 zip 檔案。R 可以列出和解壓縮這兩種檔案(請參閱函式 untarunzip),並建立這兩種檔案(對於 zip,則在外部程式協助下建立)。


附錄 A 範例會話

以下會話旨在透過使用 R 環境的某些功能來向您介紹這些功能。系統的許多功能一開始會讓人感到陌生且困惑,但這種困惑感很快就會消失。

根據您的平台適當地啟動 R(請參閱呼叫 R)。

R 程式開始執行,並會顯示標語。

(在 R 程式碼中,左側提示字元不會顯示,以避免混淆。)

help.start()

啟動HTML介面以取得線上說明(使用電腦上可用的網路瀏覽器)。您應該使用滑鼠簡要探索此功能。

將說明視窗最小化,然後繼續執行下一部分。

x <- rnorm(50)
y <- rnorm(x)

產生兩個xy座標的偽隨機常態向量。

plot(x, y)

繪製平面上點。圖形視窗將自動出現。

ls()

查看 R 工作空間中現在有哪些 R 物件。

rm(x, y)

移除不再需要的物件。(清理)。

x <- 1:20

建立x = (1, 2, ..., 20)

w <- 1 + sqrt(x)/2

標準差的「權重」向量。

dummy <- data.frame(x=x, y= x + rnorm(x)*w)
dummy

建立兩個欄資料框xy,並查看。

fm <- lm(y ~ x, data=dummy)
summary(fm)

擬合簡單的線性回歸,並查看分析。將y放在波浪符號的左側,我們正在建模依賴於xy

fm1 <- lm(y ~ x, data=dummy, weight=1/w^2)
summary(fm1)

由於我們知道標準差,我們可以執行加權迴歸。

attach(dummy)

將資料框中的欄位顯示為變數。

lrf <- lowess(x, y)

建立非參數局部迴歸函數。

plot(x, y)

標準點狀圖。

lines(x, lrf$y)

加入局部迴歸。

abline(0, 1, lty=3)

真實迴歸線:(截距 0,斜率 1)。

abline(coef(fm))

未加權迴歸線。

abline(coef(fm1), col = "red")

加權迴歸線。

detach()

從搜尋路徑中移除資料框。

plot(fitted(fm), resid(fm),
     xlab="Fitted values",
     ylab="Residuals",
     main="Residuals vs Fitted")

標準迴歸診斷圖,用於檢查異質變異性。您能看到嗎?

qqnorm(resid(fm), main="Residuals Rankit Plot")

常態分數圖,用於檢查偏度、峰度和異常值。(在此處不太有用。)

rm(fm, fm1, lrf, x, dummy)

再次清除。

下一部分將探討 Michelson 的經典實驗中用於測量光速的資料。此資料集可在 morley 物件中取得,但我們將讀取它以說明 read.table 函數。

filepath <- system.file("data", "morley.tab" , package="datasets")
filepath

取得資料檔案的路徑。

file.show(filepath)

選擇性。查看檔案。

mm <- read.table(filepath)
mm

將 Michelson 資料讀入資料框中,並查看它。有五個實驗(欄位 Expt),每個實驗有 20 次執行(欄位 Run),而 sl 是適當編碼的記錄光速。

mm$Expt <- factor(mm$Expt)
mm$Run <- factor(mm$Run)

ExptRun 變更為因子。

attach(mm)

讓資料框在位置 2(預設)可見。

plot(Expt, Speed, main="光速資料", xlab="實驗編號")

使用簡單的箱形圖比較五個實驗。

fm <- aov(Speed ~ Run + Expt, data=mm)
summary(fm)

分析為隨機區組,其中「執行」和「實驗」為因子。

fm0 <- update(fm, . ~ . - Run)
anova(fm0, fm)

擬合省略「執行」的子模型,並使用正式的變異數分析進行比較。

detach()
rm(fm, fm0)

在繼續之前進行清理。

我們現在來看一些更進階的圖形功能:等高線圖和影像圖。

x <- seq(-pi, pi, len=50)
y <- x

x 是 [-pi, pi] 區間中 50 個等距值的向量。y 相同。

f <- outer(x, y, function(x, y) cos(y)/(1 + x^2))

f 是個方陣,其列和行分別由 xy 編號,且包含函數 cos(y)/(1 + x^2) 的值。

oldpar <- par(no.readonly = TRUE)
par(pty="s")

儲存繪圖參數,並將繪圖區域設定為「正方形」。

contour(x, y, f)
contour(x, y, f, nlevels=15, add=TRUE)

建立 f 的等高線圖;加入更多線條以增加細節。

fa <- (f-t(f))/2

faf 的「不對稱部分」。(t() 是轉置)。

contour(x, y, fa, nlevels=15)

建立等高線圖,…

par(oldpar)

… 並還原舊的圖形參數。

image(x, y, f)
image(x, y, fa)

建立一些高密度影像圖表(如果需要,您可以取得其硬拷貝)…

objects(); rm(x, y, f, fa)

…並在繼續之前進行清除。

R 也可以進行複雜的運算。

th <- seq(-pi, pi, len=100)
z <- exp(1i*th)

1i 用於複數 i

par(pty="s")
plot(z, type="l")

繪製複數參數表示繪製虛部與實部。這應該是一個圓形。

w <- rnorm(100) + rnorm(100)*1i

假設我們想要在單位圓內取樣點。一種方法是取實部和虛部為標準常態分配的複數…

w <- ifelse(Mod(w) > 1, 1/w, w)

…並將圓外的任何點對映到其倒數。

plot(w, xlim=c(-1,1), ylim=c(-1,1), pch="+",xlab="x", ylab="y")
lines(z)

所有點都在單位圓內,但分佈並不均勻。

w <- sqrt(runif(100))*exp(2*pi*runif(100)*1i)
plot(w, xlim=c(-1,1), ylim=c(-1,1), pch="+", xlab="x", ylab="y")
lines(z)

第二種方法使用均勻分佈。現在這些點看起來應該更均勻地分布在圓盤上。

rm(th, w, z)

再次清除。

q()

退出 R 程式。系統會詢問您是否要儲存 R 工作空間,對於像這樣的探索性工作階段,您可能不需要儲存它。


附錄 B 呼叫 R

Windows 或 macOS 上的 R 使用者應先閱讀特定作業系統的部分,但命令列使用也受支援。


B.1 從命令列呼叫 R

在 UNIX 或 Windows 上的命令列中工作時,命令「R」可用於以以下形式啟動 R 主程式

R [options] [<infile] [>outfile],

或透過 R CMD 介面,作為各種 R 工具的包裝器(例如,用於處理 R 文件格式中的檔案或操作附加套件),這些工具並非用於「直接」呼叫。

在 Windows 命令列中,Rterm.exe 優於 R

您需要確保環境變數 TMPDIR 未設定,或它指向一個可建立暫時檔案和目錄的有效位置。

大部分選項控制 R 工作階段開始和結束時會發生什麼事。啟動機制如下(另請參閱主題「Startup」的線上說明,以取得更多資訊,以及下方部分的某些 Windows 特定詳細資料)。

  • 除非已指定 --no-environ,R 會搜尋使用者和網站檔案以設定環境變數。網站檔案的名稱是由環境變數 R_ENVIRON 指出的;如果未設定,則會使用 R_HOME/etc/Renviron.site(如果存在)。使用者檔案是由環境變數 R_ENVIRON_USER 指出的(如果已設定);否則,會搜尋目前或使用者家目錄中(依此順序)的 .Renviron 檔案。這些檔案應包含「名稱=」格式的列。(請參閱 help("Startup") 以取得精確說明。)您可能想設定的變數包括 R_PAPERSIZE(預設紙張大小)、R_PRINTCMD(預設列印指令)和 R_LIBS(指定搜尋附加套件的 R 函式庫樹清單)。
  • 接著,除非已指定命令列選項 --no-site-file,否則 R 會搜尋網站範圍的啟動設定檔。此檔案的名稱取自 R_PROFILE 環境變數的值。如果未設定該變數,則會使用預設 R_HOME/etc/Rprofile.site(如果存在)。
  • 接著,除非已指定 --no-init-file,否則 R 會搜尋使用者設定檔並載入它。此檔案的名稱取自環境變數 R_PROFILE_USER;如果未設定,則會搜尋目前目錄或使用者家目錄中(依此順序)的名為 .Rprofile 的檔案。
  • 如果當前目錄中有一個已儲存的工作區,它也會從檔案 .RData 中載入(除非指定 --no-restore--no-restore-data)。
  • 最後,如果函式 .First() 存在,它會被執行。此函式(以及在 R 會話結束時執行的 .Last())可以在適當的啟動設定檔中定義,或存在於 .RData 中。

此外,還有用於控制 R 程序可用記憶體的選項(有關更多資訊,請參閱主題「Memory」的線上說明)。使用者通常不需要使用這些選項,除非他們嘗試限制 R 使用的記憶體量。

R 接受下列命令列選項。

--help
-h

將簡短的說明訊息列印到標準輸出,然後成功結束。

--version

將版本資訊列印到標準輸出,然後成功結束。

--encoding=enc

指定假設從主控台或 stdin 輸入的編碼。這必須是 iconv 已知的編碼:請參閱其說明頁面。(--encoding enc 也被接受。)輸入會重新編碼為 R 執行的區域設定,並且需要能夠用後者的編碼表示(因此,例如,除非區域設定使用 UTF-8 編碼,否則您無法在法語區域設定中重新編碼希臘文字)。

RHOME

將 R「主目錄」的路徑列印到標準輸出,然後成功結束。除了前端 shell 腳本和手冊頁面外,R 安裝會將所有內容(可執行檔、套件等)放入此目錄中。

--save
--no-save

控制是否在 R 會話結束時儲存資料集。如果在互動式會話中都沒有給定,當使用 q() 結束會話時,會詢問使用者所需的行為;在非互動式使用中,必須指定其中一個或由其他選項暗示(請參閱下方)。

--no-environ

不要讀取任何使用者檔案來設定環境變數。

--no-site-file

啟動時不要讀取網站範圍的設定檔。

--no-init-file

啟動時不要讀取使用者的設定檔。

--restore
--no-restore
--no-restore-data

控制在啟動時是否要還原已儲存的影像(在 R 啟動的目錄中的檔案 .RData)。預設為還原。(--no-restore 暗示所有特定的 --no-restore-* 選項。)

--no-restore-history

控制在啟動時是否要還原歷程記錄檔(通常是 R 啟動的目錄中的檔案 .Rhistory,但可以透過環境變數 R_HISTFILE 設定)。預設為還原。

--no-Rconsole

(僅限 Windows)防止在啟動時載入 Rconsole 檔案。

--vanilla

結合 --no-save--no-environ--no-site-file--no-init-file--no-restore。在 Windows 中,這也包含 --no-Rconsole

-f 檔案
--file=檔案

(不是 Rgui.exe)從 檔案 接收輸入:‘-’ 表示 stdin。暗示 --no-save,除非已設定 --save。在類 Unix 系統上,應避免在 檔案 中使用 shell 超字元(但允許有空白)。

-e 表達式

(不是 Rgui.exe)使用 表達式 作為輸入行。可以使用一個或多個 -e 選項,但不能與 -f--file 一起使用。暗示 --no-save,除非已設定 --save。(以這種方式使用的表達式的總長度限制為 10,000 位元組。包含空白或 shell 超字元的表達式需要加上引號。)

--no-readline

(僅限 UNIX) 透過 readline 關閉命令列編輯。這在使用 ESS(「Emacs Speaks Statistics」)套件從 Emacs 中執行 R 時很有用。如需更多資訊,請參閱 命令列編輯器。命令列編輯已啟用以供預設互動使用(請參閱 --interactive)。此選項也會影響波浪號展開:請參閱 path.expand 的說明。

--min-vsize=N
--min-nsize=N

僅供專家使用:分別設定向量堆積 (以位元組為單位) 和 cons 單元格 (數字) 的垃圾回收初始觸發大小。字尾「M」分別指定百萬位元組或百萬個單元格。預設值分別為 6Mb 和 350k,也可以透過環境變數 R_NSIZER_VSIZE 設定。

--max-ppsize=N

將指標保護堆疊的最大大小指定為 N 個位置。預設值為 10000,但可以增加以允許執行大型且複雜的計算。目前接受的最大值為 100000。

--quiet
--silent
-q

不要列印初始版權和歡迎訊息。

--no-echo

讓 R 盡可能安靜地執行。此選項旨在支援使用 R 計算結果的程式。這表示 --quiet--no-save

--interactive

(僅限 UNIX) 即使輸入已重新導向,仍宣告 R 確實以互動方式執行:如果輸入來自 FIFO 或管線,且由互動式程式提供。(預設為僅當 stdin 連接到終端機或 pty 時,才推斷 R 以互動方式執行。)使用 -e-f--file 宣告非互動式使用,即使已提供 --interactive

請注意,這不會開啟命令列編輯。

--ess

(僅限 Windows) 設定 Rterm,供 ESS 中的 R-inferior-mode 使用,包括宣告互動式使用 (不含命令列編輯器) 和不暫存 stdout

--verbose

列印更多進度資訊,特別是將 R 的選項 verbose 設定為 TRUE。R 程式碼使用此選項來控制診斷訊息的列印。

--debugger=name
-d name

(僅限 UNIX) 透過偵錯程式 name 執行 R。對於大多數偵錯程式 (例外為 valgrindgdb 的最新版本),將忽略進一步的命令列選項,而應在從偵錯程式內部啟動 R 可執行檔時提供這些選項。

--gui=type
-g type

(僅限 UNIX) 使用 type 作為圖形使用者介面 (請注意,這也包括互動式圖形)。目前,type 的可能值為「X11」(預設值),以及在提供「Tcl/Tk」支援的情況下為「Tk」。(為保持向後相容性,接受「x11」和「tk」)。

--arch=name

(僅限 UNIX) 執行指定的子架構。

--args

此旗標除了導致命令列的其餘部分被跳過之外,什麼事都不做:這對於使用 commandArgs(TRUE) 從中擷取值時很有用。

請注意,輸入和輸出可以用通常的方式重新導向(使用「<」和「>」),但 4095 位元組的行長度限制仍然適用。警告和錯誤訊息會傳送至錯誤頻道(stderr)。

命令 R CMD 允許呼叫各種與 R 結合使用時有用的工具,但並非打算「直接」呼叫。一般形式為

R CMD command args

其中 command 是工具的名稱,而 args 是傳遞給它的引數。

目前,有下列工具可用。

BATCH

在批次模式下執行 R。執行 R --restore --save,並可能加上其他選項(請參閱 ?BATCH)。

COMPILE

(僅限 UNIX)編譯 C、C++、Fortran … 檔案以與 R 搭配使用。

SHLIB

建立共享函式庫以進行動態載入。

INSTALL

安裝附加套件。

REMOVE

移除附加套件。

build

建立(即打包)附加套件。

check

檢查附加套件。

LINK

(僅限 UNIX)建立可執行程式的前端。

Rprof

後處理 R 分析檔案。

Rdconv
Rd2txt

將 Rd 格式轉換為各種其他格式,包括 HTML、LaTeX、純文字,以及擷取範例。 Rd2txt 可用作 Rd2conv -t txt 的簡寫。

Rd2pdf

將 Rd 格式轉換為 PDF。

Stangle

從 Sweave 或其他摘要文件擷取 S/R 程式碼

Sweave

處理 Sweave 或其他小插圖文件

Rdiff

忽略標頭等資訊的 R 輸出差異

config

取得組態資訊

javareconf

(僅 Unix)更新 Java 組態變數

rtags

(僅 Unix)從 C、R 和 Rd 檔案建立 Emacs 風格的標籤檔案

open

(僅 Windows)透過 Windows 的檔案關聯開啟檔案

texify

(僅 Windows)使用 R 的樣式檔案處理 (La)TeX 檔案

使用

R CMD command --help

取得可透過 R CMD 介面存取的每個工具的使用資訊。

此外,您可以在 RCMD 之間使用選項 --arch=--no-environ--no-init-file--no-site-file--vanilla:這些選項會影響工具執行的所有 R 程序。(這裡的 --vanilla 等同於 --no-environ --no-site-file --no-init-file。)不過,請注意 R CMD 本身不會使用任何 R 啟動檔案(特別是使用者或網站 Renviron 檔案),而且這些工具執行的所有 R 程序(BATCH 除外)都會使用 --no-restore。大部分會使用 --vanilla,因此不會呼叫任何 R 啟動檔案:目前的例外是 INSTALLREMOVESweaveSHLIB(使用 --no-site-file --no-init-file)。

R CMD cmd args

路徑上的任何其他可執行檔 cmd 或由絕對檔案路徑給定的可執行檔:這對於擁有與 R 或在特定命令下執行的環境相同很有用,例如執行 lddpdflatex。在 Windows 中,cmd 可以是可執行檔或批次檔,或者如果其副檔名為 .sh.pl,則會呼叫適當的直譯器(如果可用)來執行它。


B.2 在 Windows 下呼叫 R

在 Windows 下執行 R 有兩種方式。在終端機視窗中(例如 cmd.exe 或更強大的 shell),可以使用前一節所述的方法,呼叫 R.exe 或更直接地呼叫 Rterm.exe。對於互動式使用,有一個基於主控台的 GUI(Rgui.exe)。

Windows 下的啟動程序與 UNIX 下非常相似,但需要釐清對「主目錄」的參照,因為這在 Windows 中並不總是定義的。如果環境變數 R_USER 已定義,則它會提供主目錄。接下來,如果環境變數 HOME 已定義,則它會提供主目錄。在這些兩個使用者可控制的設定之後,R 會嘗試尋找系統定義的主目錄。它首先嘗試使用 Windows 的「個人」目錄(在最近版本的 Windows 中通常為 我的文件)。如果失敗,並且環境變數 HOMEDRIVEHOMEPATH 已定義(它們通常已定義),則它們會定義主目錄。如果所有這些都失敗,則主目錄會視為起始目錄。

您需要確保環境變數 TMPDIRTMPTEMP 不是未設定,就是其中一個指向一個有效的位置來建立暫存檔案和目錄。

環境變數可以在命令列上提供為「名稱=」對。

如果有一個以 .RData 結尾的引數(無論大小寫),它會被解釋為要還原的工作區路徑:它暗示 --restore 並將工作目錄設定為命名檔案的父目錄。(此機制用於拖放和與 RGui.exe 的檔案關聯,但對 Rterm.exe 也有效。如果命名檔案不存在,如果父目錄存在,它會設定工作目錄。)

呼叫 RGui.exe 時,可以使用下列額外的命令列選項。

--mdi
--sdi
--no-mdi

控制 Rgui 是否以 MDI 程式(在一個主視窗中有多個子視窗)或 SDI 應用程式(主控台、圖形和尋呼機有多個頂層視窗)執行。命令列設定會覆寫使用者 Rconsole 檔案中的設定。

--debug

Rgui 中啟用「中斷至偵錯程式」功能表項目,並在命令列處理期間觸發中斷至偵錯程式。

在 Windows 中使用 R CMD 時,您也可以指定自己的 .bat.exe.sh.pl 檔案。它會在適當的直譯器(.pl 的 Perl)中執行,並設定幾個環境變數,包括 R_HOMER_OSTYPEPATHBSTINPUTSTEXINPUTS。例如,如果您在路徑中已有 latex.exe,則

R CMD latex.exe mydoc

會在 mydoc.tex 上執行 LaTeX,並將 R 的 share/texmf 巨集的路徑附加到 TEXINPUTS。(很遺憾,這對 LaTeX 的 MiKTeX 建置沒有幫助,但 R CMD texify mydoc 在這種情況下會起作用。)


B.3 在 macOS 中呼叫 R

有兩種方法可以在 macOS 中執行 R。在 Terminal.app 視窗中呼叫 R,第一個小節中所述的方法適用。還有一個基於主控台的 GUI (R.app),預設安裝在系統的 Applications 資料夾中。它是一個標準的 macOS 應用程式,可以按兩下開啟。

macOS 下的啟動程序與 UNIX 下的非常類似,但 R.app 不使用命令列引數。‘主目錄’是 R.framework 內的目錄,但啟動和目前工作目錄設定為使用者的主目錄,除非在 GUI 內可存取的「喜好設定」視窗中提供不同的啟動目錄。


B.4 使用 R 撰寫指令碼

如果您只想執行一個 R 指令檔案 foo.R,建議的方式是使用 R CMD BATCH foo.R。如果您想在背景中或當作批次工作執行,請使用作業系統特定的功能來執行:例如,在類 Unix 作業系統上的大多數 shell 中,R CMD BATCH foo.R & 會執行背景工作。

您可以透過命令列中的其他引數將參數傳遞給指令碼:例如(引號的精確需求會依據使用的 shell 而定)

R CMD BATCH "--args arg1 arg2" foo.R &

會將引數傳遞給指令碼,可以透過以下方式擷取為字元向量

args <- commandArgs(TRUE)

透過替代前端 Rscript 可以簡化這個動作,可以透過以下方式呼叫

Rscript foo.R arg1 arg2

也可以用來撰寫可執行指令碼檔案,例如(至少在類 Unix 和一些 Windows shell 中)

#! /path/to/Rscript
args <- commandArgs(TRUE)
...
q(status=<exit status code>)

如果這輸入到文字檔案 runfoo 中,並讓它可以執行(透過 chmod 755 runfoo),可以透過以下方式呼叫不同的引數

runfoo arg1 arg2

如需更多選項,請參閱 help("Rscript")。這會將 R 輸出寫入 stdoutstderr,這可以用執行命令的 shell 的通常方式重新導向。

如果您不希望硬編碼路徑至 Rscript,但已將其放在您的路徑中(這通常是已安裝 R 的情況,但 Windows 除外,例如 macOS 使用者可能需要將 /usr/local/bin 加入其路徑),請使用

#! /usr/bin/env Rscript
...

至少在 Bourne 和 bash shell 中,#! 機制允許額外引數,例如 #! /usr/bin/env Rscript --vanilla

要考慮的一件事是 stdin() 指的是什麼。使用類似以下區段撰寫 R 腳本是很常見的

chem <- scan(n=24)
2.90 3.10 3.40 3.40 3.70 3.70 2.80 2.50 2.40 2.40 2.70 2.20
5.28 3.37 3.03 3.03 28.95 3.77 3.40 2.20 3.50 3.60 3.70 3.70

stdin() 指的是腳本檔案,以允許此類傳統使用方式。如果您想要指涉程序的 stdin,請將 "stdin" 用作 file 連線,例如 scan("stdin", ...)

撰寫可執行腳本檔案的另一種方式(由 François Pinard 建議)是使用類似以下的here 文件

#!/bin/sh
[environment variables can be set here]
R --no-echo [other options] <<EOF

   R program goes here...

EOF

但這裡 stdin() 指的是程式來源,且 "stdin" 將無法使用。

短腳本可透過 -e 旗標傳遞至命令列上的 Rscript。(不接受空腳本。)

請注意,在類 Unix 系統上,輸入檔名(例如 foo.R)不應包含空白或 shell 超字元。


附錄 C 命令列編輯器

C.1 前置作業

當在 UNIX 下設定 R 編譯時,如果 GNU readline 函式庫可用,會使用內建的命令列編輯器,允許召回、編輯和重新提交先前的命令。請注意,readline 有其他版本,內建的命令列編輯器可能會使用這些版本:這在 macOS 上最為常見。您可以在 R 會話中執行 extSoftVersion(),找出有哪些版本(如果有)可用。

它可以停用(對於與 ESS 一起使用很有用 25),使用啟動選項 --no-readline

Windows 版本的 R 有較為簡單的命令列編輯:請參閱 GUI 的「說明」選單下的「主控台」,以及 README.Rterm 檔案,以了解在 Rterm.exe 下進行命令列編輯。

當與 GNU26 readline 功能一起使用 R 時,可以使用以下所述的函式,以及其他(可能)在系統上記載於 man readlineinfo readline 中的函式。

其中許多使用 Control 或 Meta 字元。Control 字元,例如 Control-m,是在按住 CTRL 的同時按下 m 鍵取得的,並寫成 C-m。Meta 字元,例如 Meta-b,是透過按住 META27 並按下 b 鍵來輸入的,並寫成 M-b。如果您的終端機沒有啟用 META 鍵,您仍可以使用從 ESC 開始的兩個字元序列來輸入 Meta 字元。因此,若要輸入 M-b,您可以輸入 ESCb。在具有真實 Meta 鍵的終端機上也允許使用 ESC 字元序列。請注意,Meta 字元會區分大小寫。

某些但並非所有版本的28 readline 會辨識終端機視窗的調整大小,因此最好避免這樣做。

C.2 編輯動作

R 程式會保留您輸入的命令列記錄,包括錯誤的列,且記錄中的命令可以被叫回、必要時變更,並重新提交為新的命令。在 Emacs 風格的命令列編輯中,在編輯階段進行的任何直式輸入都會導致字元插入您正在編輯的命令中,並取代游標右邊的任何字元。在 vi 模式中,字元插入模式是由 M-iM-a 開始的,字元會被輸入,並透過輸入另一個 ESC 來結束插入模式。(預設為 Emacs 風格,且僅在此處描述:有關 vi 模式,請參閱 readline 文件。)

隨時按下 RET 命令會導致命令重新提交。

其他編輯動作總結在以下表格中。

C.3 命令列編輯器摘要

指令回溯與垂直移動

C-p

前往上一個指令(在歷史紀錄中往後)。

C-n

前往下一個指令(在歷史紀錄中往前)。

C-r 文字

尋找包含 文字 字串的最後一個指令。這可以用 C-g(在某些版本的 R 中也可以用 C-c)取消。

在大部分終端機中,你也可以使用向上和向下箭頭鍵取代 C-pC-n

游標的水平移動

C-a

前往指令的開頭。

C-e

前往該行的結尾。

M-b

往回一個字。

M-f

往前一個字。

C-b

往回一個字元。

C-f

往前一個字元。

在大部分終端機中,你也可以使用向左和向右箭頭鍵取代 C-bC-f

編輯與重新提交

文字

在游標處插入 文字

C-f 文字

在游標後方加上 文字

DEL

刪除前一個字元(在游標左側)。

C-d

刪除游標下的字元。

M-d

刪除游標下剩餘的字詞,並「儲存」它。

C-k

從游標刪除到指令結尾,並「儲存」它。

C-y

在此處插入(yank)最後一個「儲存」的文字。

C-t

將游標下的字元與下一個字元交換。

M-l

將剩餘的字詞改為小寫。

M-c

將其餘文字變為大寫。

RET

將指令重新提交至 R。

最後的 RET 終止指令列編輯序列。

readline 鍵盤繫結可以透過一般的 via ~/.inputrc 檔案自訂。這些自訂可以依據應用程式 R 進行設定,也就是包含類似下列的區段

$if R
  "\C-xd": "q('no')\n"
$endif

附錄 D 函式和變數索引

跳至:  -   :   !   ?   .   *   /   &   %   ^   +   <   =   >   |   ~  
A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X  
索引條目區段

-
-向量運算

:
:產生規則序列
::命名空間
:::命名空間

!
!邏輯向量
!=邏輯向量

?
?取得說明
??取得說明

.
.更新擬合模型
.First自訂環境
.Last自訂環境

*
*向量運算

/
/向量運算

&
&邏輯向量
&&條件式執行

%
%*%乘法
%o%兩個陣列的外積

^
^向量運算

+
+向量運算

<
<邏輯向量
<<-範圍
<=邏輯向量

=
==邏輯向量

>
>邏輯向量
>=邏輯向量

|
|邏輯向量
||條件式執行

~
~統計模型的公式

A
abline低階繪圖指令
ace一些非標準模型
add1更新擬合模型
anova萃取模型資訊的通用函數
anovaANOVA 表格
aov變異數分析和模型比較
aperm陣列的廣義轉置
arrayarray() 函數
as.data.frame建立資料框
as.vector使用陣列的串接函數 c()
attachattach() 和 detach()
attr取得和設定屬性
attr取得和設定屬性
屬性取得和設定屬性
屬性取得和設定屬性
avas一些非標準模型
axis低階繪圖指令

B
boxplot一和二樣本檢定
break重複執行
bruto一些非標準模型

C
c向量和指定
c字元向量
c使用陣列的串接函數 c()
c串接清單
C對比
cbind建立分割矩陣
coef萃取模型資訊的通用函數
係數萃取模型資訊的通用函數
contour顯示圖形
contrasts對比
coplot顯示多變量資料
cos向量運算
crossprod索引矩陣
crossprod乘法
cut由因子產生的頻率表

D
data存取內建資料集
data.frame建立資料框
density檢查資料集的分配
det奇異值分解和行列式
detachattach() 和 detach()
行列式奇異值分解和行列式
dev.list多個圖形裝置
dev.next多個圖形裝置
dev.off多個圖形裝置
dev.prev多個圖形裝置
dev.set多個圖形裝置
deviance萃取模型資訊的通用函數
diag乘法
dim陣列
dotchart顯示圖形
drop1更新擬合模型

E
ecdf檢查資料集的分配
edit編輯資料
eigen特徵值和特徵向量
else條件式執行
Error變異數分析和模型比較
example取得說明
exp向量運算

F
F邏輯向量
factor因子
FALSE邏輯向量
fivenum檢查資料集的分配
for重複執行
formula萃取模型資訊的通用函數
function撰寫自訂函數

G
getAnywhere物件導向
getS3method物件導向
glmglm() 函數

H
help取得說明
help取得說明
help.search取得說明
help.start取得說明
hist檢查資料集的分配
hist顯示圖形

I
identify與圖形互動
if條件式執行
if條件式執行
ifelse條件式執行
image顯示圖形
is.na遺漏值
is.nan遺漏值

J
jpeg裝置驅動程式

K
ks.test檢查資料集的分配

L
legend低階繪圖指令
length向量運算
length內在屬性 mode 和 length
levels因子
lines低階繪圖指令
list清單
lm線性模型
lme一些非標準模型
locator與圖形互動
loess一些非標準模型
loess一些非標準模型
log向量運算
lqs一些非標準模型
lsfit最小平方擬合和 QR 分解

M
mars一些非標準模型
max向量運算
mean向量運算
methods物件導向
min向量運算
mode內在屬性 mode 和 length

N
NA遺漏值
NaN遺漏值
ncol矩陣功能
next重複執行
nlm非線性最小平方法和最大概似模型
nlm最小平方
nlm最大似然
nlme一些非標準模型
nlminb非線性最小平方法和最大概似模型
nrow矩陣功能

O
optim非線性最小平方法和最大概似模型
order向量運算
ordered已排序因子
ordered已排序因子
outer兩個陣列的外積

P
pairs顯示多變量資料
parpar() 函數
paste字元向量
pdf裝置驅動程式
persp顯示圖形
plot萃取模型資訊的通用函數
plotplot() 函數
pmax向量運算
pmin向量運算
png裝置驅動程式
points低階繪圖指令
polygon低階繪圖指令
postscript裝置驅動程式
predict萃取模型資訊的通用函數
print萃取模型資訊的通用函數
prod向量運算

Q
qqline檢查資料集的分配
qqline顯示圖形
qqnorm檢查資料集的分配
qqnorm顯示圖形
qqplot顯示圖形
qr最小平方擬合和 QR 分解
quartz裝置驅動程式

R
range向量運算
rbind建立分割矩陣
read.tableread.table() 函數
rep產生規則序列
repeat重複執行
resid萃取模型資訊的通用函數
residuals萃取模型資訊的通用函數
rlm一些非標準模型
rm資料的永久性和移除物件

S
scanscan() 函數
sdtapply() 函數和不規則陣列
search管理搜尋路徑
seq產生規則序列
shapiro.test檢查資料集的分配
sin向量運算
sink從檔案執行指令或將輸出導向檔案
solve線性方程式和反演
sort向量運算
source從檔案執行指令或將輸出導向檔案
split重複執行
sqrt向量運算
stem檢查資料集的分配
step萃取模型資訊的通用函數
step更新擬合模型
sum向量運算
summary檢查資料集的分配
summary萃取模型資訊的通用函數
svd奇異值分解和行列式

T
T邏輯向量
t陣列的廣義轉置
t.test一和二樣本檢定
table索引矩陣
table由因子產生的頻率表
tan向量運算
tapplytapply() 函數和不規則陣列
文字低階繪圖指令
title低階繪圖指令
tree一些非標準模型
TRUE邏輯向量

U
unclass物件的類別
update更新擬合模型

V
var向量運算
vartapply() 函數和不規則陣列
var.test一和二樣本檢定
vcov萃取模型資訊的通用函數
vector向量和指定

W
while重複執行
wilcox.test一和二樣本檢定
windows裝置驅動程式

X
X11裝置驅動程式


附錄 E 概念索引

跳至:  A   B   C   D   E   F   G   I   K   L   M   N   O   P   Q   R   S   T   U   V   W  
索引條目區段

A
存取內建資料集存取內建資料集
加法模型一些非標準模型
變異數分析變異數分析和模型比較
算術函數和運算子向量運算
陣列陣列
指定向量和指定
屬性物件

B
二元運算子定義新的二元運算子
箱形圖一和二樣本檢定

C
字元向量字元向量
類別物件的類別
類別物件導向
串接清單串接清單
對比對比
控制陳述式控制陳述式
CRAN貢獻套件和 CRAN
自訂環境自訂環境

D
資料框資料框
預設值命名引數和預設值
密度估計檢查資料集的分配
行列式奇異值分解和行列式
轉移輸入和輸出從檔案執行指令或將輸出導向檔案
動態圖形動態圖形

E
特徵值和特徵向量特徵值和特徵向量
經驗 CDF檢查資料集的分配

F
因子因子
因子對比
公式統計模型的公式

G
廣義線性模型廣義線性模型
陣列的廣義轉置陣列的廣義轉置
一般函數物件導向
圖形裝置驅動程式裝置驅動程式
圖形參數par() 函數
分組表達式分組表達式

I
陣列的索引和索引陣列索引
索引向量索引向量

K
柯爾莫哥洛夫-史密諾夫檢定檢查資料集的分配

L
最小平方法擬合最小平方擬合和 QR 分解
線性方程式線性方程式和反演
線性模型線性模型
清單清單
局部近似回歸一些非標準模型
迴圈和條件執行迴圈和條件執行

M
矩陣陣列
矩陣乘法乘法
最大似然最大似然
遺漏值遺漏值
混合模型一些非標準模型

N
命名參數命名引數和預設值
命名空間命名空間
非線性最小平方法非線性最小平方法和最大概似模型

O
物件導向物件導向
物件物件
一和二樣本檢定一和二樣本檢定
已排序因子因子
已排序因子對比
陣列的外積兩個陣列的外積

P
套件R 和統計
套件套件
機率分佈機率分佈

Q
QR 分解最小平方擬合和 QR 分解
分位數-分位數圖檢查資料集的分配

R
從檔案讀取資料從檔案讀取資料
循環使用規則向量運算
循環使用規則循環使用規則
常規序列產生規則序列
移除物件資料的永久性和移除物件
穩健回歸一些非標準模型

S
範圍範圍
搜尋路徑管理搜尋路徑
夏皮洛-威爾克檢定檢查資料集的分配
奇異值分解奇異值分解和行列式
統計模型R 中的統計模型
學生 t 檢定一和二樣本檢定

T
製表由因子產生的頻率表
基於樹的模型一些非標準模型

U
更新擬合模型更新擬合模型

V
向量簡單的數字和向量操作

W
威爾考克森檢定一和二樣本檢定
工作區資料的永久性和移除物件
撰寫函數撰寫自訂函數


附錄 F 參考文獻

D. M. Bates 和 D. G. Watts (1988),非線性回歸分析及其應用。約翰威利父子公司,紐約。

理查 A. 貝克、約翰 M. 張伯斯和艾倫 R. 威爾克斯 (1988),新 S 語言。查普曼與霍爾,紐約。這本書通常稱為「藍皮書」。

約翰 M. 張伯斯和崔佛 J. 哈斯提編輯 (1992),S 中的統計模型。查普曼與霍爾,紐約。這也稱為「白皮書」。

約翰 M. 張伯斯 (1998) 使用資料進行程式設計。施普林格,紐約。這也稱為「綠皮書」。

A. C. Davison 和 D. V. Hinkley (1997),Bootstrap Methods and Their Applications,劍橋大學出版社。

Annette J. Dobson (1990),An Introduction to Generalized Linear Models,倫敦查普曼與霍爾出版社。

Peter McCullagh 和 John A. Nelder (1989),Generalized Linear Models. 第二版,倫敦查普曼與霍爾出版社。

John A. Rice (1995),Mathematical Statistics and Data Analysis. 第二版。Duxbury Press,加州貝爾蒙特。

S. D. Silvey (1970),Statistical Inference. 倫敦企鵝出版社。


腳註

(1)

ACM 軟體系統獎,1998:https://awards.acm.org/award_winners/chambers_6640862.cfm

(2)

對於可攜式 R 程式碼(包括在 R 套件中使用的程式碼),僅應使用 A–Za–z0–9。

(3)

在字串內,也不在函式定義的參數清單中

(4)

有些主控台不允許您輸入更多內容,而在允許輸入的那些主控台中,有些會靜默地捨棄多餘的內容,有些會將其用作下一行的開頭。

(5)

長度不限。

(6)

此檔名中的開頭「點」會讓它在 UNIX 中的正常檔案清單中隱藏,以及在 macOS 和 Windows 中的預設 GUI 檔案清單中隱藏。

(7)

對於非向量類型的參數,例如 list 模式參數,c() 的動作相當不同。請參閱串接清單

(8)

實際上,在執行任何其他陳述之前,它仍然可用作 .Last.value

(9)

paste(..., collapse=ss) 將參數加入單一字元字串中,並在中間放置 ss,例如 ss <- "|"。還有更多字元處理工具,請參閱 subsubstring 的說明。

(10)

數字模式實際上是兩種不同模式的混合,即手冊中說明的整數雙精度

(11)

但請注意,length(物件)並不總是包含內在的有用資訊,例如,當物件是函數時。

(12)

一般而言,由於字元表示中的捨入誤差,從數字到字元的強制轉換和從字元到數字的強制轉換不會完全可逆。

(13)

套件methods中提供了使用「正規」或「S4」類別的不同樣式。

(14)

讀者應注意,澳洲有八個州和領地,分別是澳洲首都特區、新南威爾斯、北領地、昆士蘭、南澳洲、塔斯馬尼亞、維多利亞和西澳洲。

(15)

請注意,當tapply()的第二個引數不是因子時,例如「tapply(incomes, state)」,tapply()也會運作,這也適用於許多其他函數,因為必要時會將引數強制轉換為因子(使用as.factor())。

(16)

請注意,x %*% x是模稜兩可的,因為它可以表示x’x或x x’,其中x是欄位形式。在這種情況下,較小的矩陣似乎隱含地被採用為解釋,因此在此情況下,純量x’x是結果。矩陣x x’可以透過cbind(x) %*% xx %*% rbind(x)計算,因為rbind()cbind()的結果始終是矩陣。但是,計算x’x或x x’的最佳方式分別是crossprod(x)x %o% x

(17)

更好的方法是形成一個矩陣平方根B,其中A = BB’,並找出By = x的解的平方長度,也許使用A的Cholesky或特徵分解。

(18)

請參閱autoload的線上說明,以了解第二個術語的含義。

(19)

在 UNIX 下,可以使用工具程式 sedawk

(20)

稍後討論,或使用套件 lattice 中的 xyplot

(21)

另請參閱 R 中的統計模型 中描述的方法

(22)

在某種意義上,這模仿了 S-PLUS 中的行為,因為在 S-PLUS 中,這個運算子總是建立或指派給一個全域變數。

(23)

因此它在 UNIX 下是隱藏的。

(24)

一些圖形參數(例如目前裝置的大小)僅供參考。

(25)

「Emacs Speaks Statistics」套件;請參閱 URL https://ESS.R-project.org/

(26)

可以使用 GNU readline 模擬來建立 R,例如基於 NetBSD 的 editline(也稱為 libedit),這種情況下可能只提供部分功能。

(27)

在 PC 鍵盤上,這通常是 Alt 鍵,偶爾是「Windows」鍵。在 Mac 鍵盤上,通常沒有提供 meta 鍵。

(28)

特別是,不是版本 6.3 或更新版本:這是從 R 3.4.0 開始解決的。