Org Babel 中的 R 原始碼區塊
在 Org Babel 中使用 R 提供了一個用於統計計算、資料分析、圖形生成和可重現研究論文的環境。Org Mode 中的 R 程式碼區塊與 ESS (Emacs Speaks Statistics) 整合,以支援互動式執行、多區塊狀態共享、可出版品質的圖形和結構化表格匯出。
1. 設定與環境配置
1.1 先決條件
- 一個可運作的 R 安裝(CRAN 二進位檔或從原始碼編譯)。
- 透過 MELPA 安裝的 ESS (Emacs Speaks Statistics)(需要基於會話的評估和逐步執行)。
- 在
org-babel-load-languages中啟用ob-R。
1.2 Emacs 配置範本
將以下內容加入您的 init.el:
;; 1. 配置 MELPA
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
;; 2. 確保 ESS 已載入
(unless (package-installed-p 'ess)
(package-refresh-contents)
(package-install 'ess))
(require 'ess-r-mode)
;; 3. 在 Org Babel 中啟用 R
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(R . t)))
;; 4. 可選:執行區塊時不顯示互動式安全確認提示
(setq org-confirm-babel-evaluate nil)
1.3 Windows 特有設定
在 Microsoft Windows 上,如果 Emacs 報告「系統找不到指定的路徑」,請明確設定 R 二進位檔路徑(包含預設的 Babel 旗標 --slave --no-save):
;; 適用於 64 位元 Windows:
(setq org-babel-R-command "C:/Progra~1/R/R-4.3.0/bin/x64/R --slave --no-save")
注意: 使用 :session 時,org-babel-R-command 會被忽略,改為使用 ESS 的 inferior-ess-R-program。
2. 執行模式:會話與 ESS 整合
2.1 非會話模式(:session none,預設)
在一個分離的批次 R 程序(R --slave --no-save)中執行。乾淨、隔離且無副作用,但每次都需要重新載入所有函式庫和資料。
2.2 互動式會話(:session <名稱>)
在一個下層的 ESS R 程序(*<名稱>*)內執行。
- 資料集、函式庫、模型和變數在共用相同會話名稱的多個區塊之間持續存在。
- 啟用互動式檢查、除錯和快速的迭代工作流程。
#+PROPERTY: header-args:R :session *r-analysis* :results value :exports both
2.3 使用 ESS 進行互動式除錯與逐步執行
在對 R 區塊進行故障排除時:
- 切換到會話: 將游標置於 R 區塊內,按下
M-<down>(org-babel-pop-to-session) 或C-c C-z(ess-switch-to-end-of-ESS) 以跳轉到 R REPL 緩衝區。 - 檢查環境: 使用
ls()、str(x)、dim(x)、summary(x)或head(x)。 - 逐行逐步執行:
- 在 Org 區塊內按下
C-c '(org-edit-special) 進入專用的 ESS R 緩衝區。 - 使用
C-c C-n(ess-eval-line-and-step) 或C-c C-c(ess-eval-region-or-function-or-paragraph) 在活動的 R 程序中逐行執行程式碼。 - 按下
C-c '返回 Org 文檔。
- 在 Org 區塊內按下
3. 結果處理:資料框、數值與表格
3.1 回傳表格資料(:results value table)
當回傳資料框、矩陣或向量時,Org Babel 會直接將它們轉換為原生的 Org 表格:
#+NAME: mtcars_summary
#+BEGIN_SRC R :session *r* :results value table :colnames yes
aggregate(mpg ~ cyl + gear, data=mtcars, FUN=mean)
#+END_SRC
#+RESULTS: mtcars_summary
| cyl | gear | mpg |
|-----+------+------------------|
| 4 | 3 | 21.5 |
| 6 | 3 | 19.7500000000000 |
| 8 | 3 | 15.0500000000000 |
| 4 | 4 | 26.92 |
| 6 | 4 | 19.75 |
| 4 | 5 | 28.2 |
| 6 | 5 | 19.7 |
| 8 | 5 | 15.4 |
- 在處理資料框時,始終添加
:colnames yes以正確保留和顯示欄位名稱。 - 在 R 中,最後一個評估表達式的值會自動回傳(不需要明確的
return())。
3.2 捕獲列印的終端機輸出(:results output)
使用 :results output 來捕獲標準輸出、模型列印輸出或摘要統計:
#+BEGIN_SRC R :session *r* :results output
fit <- lm(mpg ~ wt + hp, data=mtcars)
summary(fit)$coefficients
#+END_SRC
#+RESULTS:
: Estimate Std. Error t value Pr(>|t|)
: (Intercept) 37.2272694 1.59878754 23.284688 2.565459e-20
: wt -3.8778307 0.63273349 -6.128695 1.119647e-06
: hp -0.0317729 0.00902971 -3.518708 1.451229e-03
4. 圖形與視覺化
4.1 基礎圖形規則(Org ≥ 9.3)
為了產生圖形,請在 :results 中同時指定 file 和 graphics,並在 :file 中指定輸出檔案名稱:
:results graphics file :file <路徑.副檔名>
支援的檔案副檔名與對應的 R 裝置:
- 向量圖:
.pdf、.svg、.ps/.postscript、.tex(TikZ) - 點陣圖:
.png、.jpg/.jpeg、.tiff、.bmp - 預設後備:
.png
#+BEGIN_SRC R :file figures/base_plot.png :results graphics file :width 600 :height 400 :res 120
plot(mtcars$wt, mtcars$mpg, pch=19, col="darkblue",
xlab="Weight (1000 lbs)", ylab="Miles per Gallon",
main="Fuel Economy")
abline(lm(mpg ~ wt, data=mtcars), col="red", lwd=2)
#+END_SRC
#+RESULTS:
[[file:figures/base_plot.png]]
4.2 關鍵的 ggplot2 / Lattice「網格圖形」規則
陷阱: Lattice (xyplot) 和 ggplot2 函數回傳的是圖形物件。在非互動式批次評估(非會話模式)中,回傳該物件而不將其列印出來,會產生空白/損壞的圖形檔案!
在 Org Babel 中渲染 ggplot2 / Lattice 圖形有三種可靠的方法:
方法 A:明確的 print()(非會話模式推薦)
#+BEGIN_SRC R :file figures/dist.png :results graphics file
library(ggplot2)
p <- ggplot(mtcars, aes(x=mpg)) + geom_histogram(bins=10, fill="steelblue")
print(p) # 明確的 print() 觸發圖形裝置渲染
#+END_SRC
方法 B:使用 :session(互動式自動列印)
#+BEGIN_SRC R :session *r* :file figures/dist.png :results graphics file
library(ggplot2)
ggplot(mtcars, aes(x=mpg)) + geom_histogram(bins=10, fill="steelblue")
#+END_SRC
方法 C:使用 :results output graphics file
#+BEGIN_SRC R :file figures/dist.png :results output graphics file
library(lattice)
xyplot(mpg ~ wt, data=mtcars)
#+END_SRC
5. R 圖形裝置標頭引數
Org Babel 提供一級標頭引數,直接映射到 R 圖形裝置(png()、pdf()、svg() 等)的參數:
| 標頭引數 | 預設值 | 描述與允許值 |
|---|---|---|
:width | 7 (in) / 480 (px) | 裝置寬度。 |
:height | 7 (in) / 480 (px) | 裝置高度。 |
:units | px (點陣圖), in (PDF) | 單位:"px"、"in"、"cm"、"mm"。 |
:res | 72 | 每英吋的標稱像素數 (DPI)。 (對於清晰的點陣圖至關重要:使用 150-300)。 |
:bg | "white" | 背景顏色(例如 "transparent"、"#f7f7f7")。 |
:fg | "black" | 前景顏色。 |
:pointsize | 12 | 文字渲染的基本點大小。 |
:family | "Helvetica" | 字型家族("Helvetica"、"Times"、"Palatino"、"Courier"、"sans"、"serif"、"mono")。 |
:quality | 75 | JPEG 品質百分比 (1-100)。 |
:type | 平台預設 | 點陣圖渲染器:"cairo"、"quartz" 或 "Xlib"。 |
:paper | "special" | PDF 紙張大小:"special"、"a4"、"letter"、"a4r" 等。 |
:R-dev-args | nil | 直接傳遞給裝置函數的附加 R 裝置引數原始字串。 |
範例:高 DPI Cairo SVG/PNG 與自訂尺寸
#+NAME: custom_styled_plot
#+HEADER: :width 8 :height 5 :units in :res 300 :type cairo
#+HEADER: :R-dev-args bg="#fcfcfc"
#+BEGIN_SRC R :session *r* :file figures/styled_plot.png :results graphics file
library(ggplot2)
ggplot(diamonds[1:1000, ], aes(x=carat, y=price, color=cut)) +
geom_point(alpha=0.6) +
theme_minimal(base_family="sans") +
labs(title="Diamond Prices by Carat and Cut")
#+END_SRC
5.3 用於匹配文件字型的 TikZ LaTeX 圖形
若要產生軸標籤和數學註解與文件使用完全相同 LaTeX 字型的圖形:
#+BEGIN_SRC R :file figures/model_plot.tex :results graphics file
plot(1:10, type="b", main="\\textbf{TikZ Plot with Math: } $\\int_0^1 x^2 dx$")
#+END_SRC
匯出為 LaTeX/PDF 時,.tex 檔案會透過 \input{figures/model_plot.tex} 原生包含!
6. 進階格式化輸出 (ASCII、Org 與 LaTeX)
6.1 使用 ascii 套件的格式化 Org 輸出
R 套件 ascii 可以將複雜的非表格 R 物件(如 describe()、table() 或 summary())強制轉換為原生的 Org 語法:
#+BEGIN_SRC R :session *r* :results output org
library(ascii)
options(asciiType = "org")
tab <- table(mtcars$cyl, mtcars$gear)
ascii(tab, caption="Cylinders vs Forward Gears")
#+END_SRC
#+RESULTS:
#+BEGIN_ORG
#+CAPTION: Cylinders vs Forward Gears
| | 3 | 4 | 5 |
|---+----+---+---|
| 4 | 1 | 8 | 2 |
| 6 | 2 | 4 | 1 |
| 8 | 12 | 0 | 2 |
#+END_ORG
6.2 使用 xtable 產生用於 LaTeX 匯出的出版級表格
對於目標為透過 LaTeX 匯出成 PDF 的文檔,請搭配 :results output latex 使用 xtable:
#+BEGIN_SRC R :results output latex :exports results
library(xtable)
fit <- lm(mpg ~ wt + hp, data=mtcars)
print(xtable(summary(fit), caption="Regression Estimates", label="tab:reg"),
comment=FALSE)
#+END_SRC
#+RESULTS:
#+BEGIN_LaTeX
\begin{table}[ht]
\centering
\begin{tabular}{rrrrr}
\hline
& Estimate & Std. Error & t value & Pr($>$$|$t$|$) \\
\hline
(Intercept) & 37.2273 & 1.5988 & 23.28 & 0.0000 \\
wt & -3.8778 & 0.6327 & -6.13 & 0.0000 \\
hp & -0.0318 & 0.0090 & -3.52 & 0.0015 \\
\hline
\end{tabular}
\caption{Regression Estimates}
\label{tab:reg}
\end{table}
#+END_LaTeX
7. 故障排除與常見陷阱
| 問題 | 原因 | 解決方案 |
|---|---|---|
| ggplot2 或 lattice 產生空白/損壞的影像 | 在非會話模式下,回傳的圖形物件未明確列印 | 將繪圖包裝在 print(p) 中,或切換到 :session,或在 :results output graphics file 中加入 output。 |
| 已產生圖形檔案,但未插入連結 | 缺少 file 或 graphics 關鍵字 | 確保標頭包含 :results graphics file(在 Org ≥ 9.3 中,兩個詞都是必需的)。 |
| 「系統找不到指定的路徑」(Windows) | PATH 中找不到 R 可執行檔,或位於自訂位置 | 在 init.el 中設定 (setq org-babel-R-command "path/to/R --slave --no-save")。 |
| R 資料框中的欄位被轉換為第 0 列 | 表格欄位標題被視為觀測資料 | 在區塊標頭引數中加入 :colnames yes。 |
| 會話中的 R 在大計算量時掛起 | 區塊正在阻塞 Emacs 程序 | 切換到下層的 ESS 緩衝區 (C-c C-z) 以監控進度,或使用 C-c C-c 中斷。 |
| 匯出文件中的圖形模糊 | 預設點陣圖 DPI (72) 太低 | 加入 :res 300 並相應調整 :width 和 :height。 |