使用Emacs/ESS构建R语言统计分析

14
我正在寻找一种结构化我的统计分析方法。 我目前使用Emacs/ESS,分析文件非常长。 我已经开始将代码的部分放入可源代码化函数中并存储在单独的文件中,但是...

我想引入某种子标题/节标题到文件中(聚合,群集分析,模拟...),并在下面编写代码,这样我就可以快速跳转到我想要处理的部分。

我猜我可以只使用注释并搜索它们,但是那样我无法获得概述或索引。 我还考虑使用Org-Mode作为标题,但这对于与另一个编辑器合作的协作者来说可能不太方便。

我知道R-Studio实现了这个功能,所以Emacs也会有解决方法,对吧?

非常感谢!

PS:像imenu这样的工具可以用于函数,但不适用于节标题。

6个回答

15

一般情况下,我使用org-mode和org-babel进行编程,但是当我需要与他人共享脚本时,我会在我的.emacs中添加以下内容:

(defgroup ess-jb-faces nil
  "Faces used by cutomized ess-mode"
  :group 'faces)

(defface ess-jb-comment-face
  '((t (:background "cornsilk" 
    :foreground "DimGrey"
    :inherit font-lock-comment-face)))
  "Face used to highlight comments."
  :group 'ess-jb-faces)

(defface ess-jb-comment-bold-face
  '((t (:weight bold
    :inherit ess-jb-comment-face)))
  "Face used to highlight bold in comments."
  :group 'ess-jb-faces)

(defface ess-jb-h1-face
  '((t (:height 1.6 
    :weight bold 
    :foreground "MediumBlue"
    :inherit ess-jb-comment-face)))
  "Face used to highlight h1 headers."
  :group 'ess-jb-faces)

(defface ess-jb-h2-face
  '((t (:height 1.2 
    :weight bold 
    :foreground "DarkViolet"
    :inherit ess-jb-comment-face)))
  "Face used to highlight h2 headers."
  :group 'ess-jb-faces)

(defface ess-jb-h3-face
  '((t (:height 1.0 
    :weight bold 
    :foreground "DarkViolet"
    :inherit ess-jb-comment-face)))
  "Face used to highlight h3 headers."
  :group 'ess-jb-faces)

(defface ess-jb-hide-face
  '((t (:foreground "white"
    :background "white"
    :inherit ess-jb-comment-face)))
  "Face used to hide characters."
  :group 'ess-jb-faces)

(font-lock-add-keywords 'ess-mode
   '(("^###\\(#\\)\\([^#].*\\)$" (1 'ess-jb-hide-face t)(2 'ess-jb-h1-face t))
     ("^###\\(##\\)\\([^#].*\\)$" (1 'ess-jb-hide-face t)(2 'ess-jb-h2-face t))
     ("^###\\(###\\)\\([^#].*\\)$" (1 'ess-jb-hide-face t)(2 'ess-jb-h3-face t))
     ("^###\\( .*\\|$\\)" 1 'ess-jb-comment-face t)
     ("^###" "\\*.*?\\*" nil nil (0 'ess-jb-comment-bold-face append))
     ))

使用此功能,任何以####开头的行都会被格式化为“标题1”。任何以#####开头的行都会被格式化为“标题2”,以此类推。以###开头的行将被视为具有特殊字体锁定的注释(用于长注释)。这可以产生以下效果:

enter image description here

这种方法有些不太正规,但它的优点在于只使用标准R注释,因此可以与他人轻松共享。通常我将以下内容用作“标题1”:其他人看到的是下面的样子,而我则享受自定义的字体锁定:
############################################
#### HEADER 1
############################################

使用这个语法,你也可以使用下面的代码来激活outline-minor-mode并能够折叠/展开之前定义的部分:
(add-hook 'ess-mode-hook
      '(lambda ()
         (auto-complete-mode nil)
         (outline-minor-mode 1)
         (setq outline-regexp "\\(^#\\{4,6\\}\\)\\|\\(^[a-zA-Z0-9_\.]+ ?<- ?function(.*{\\)")
         (setq outline-heading-alist
           '(("####" . 1) ("#####" . 2) ("######" . 3)
             ("^[a-zA-Z0-9_\.]+ ?<- ?function(.*{" .4)))))

所有这些代码都没有经过很好的测试,而且我远非emacs lisp专家,所以可能有更好的方法来实现它,如果出现错误,请不要感到惊讶!


我花了一些时间才尝试您的建议。但最近我尝试了一下,字体锁定起作用了。但是我在emacs中使用了一个黑色主题('zenburn'),现在字体锁定的标题有白色背景,这对眼睛有点刺眼。从您的截图来看,似乎您已经解决了这个问题。 - stats-hb
我成功地将hideface-background更改为与我的主题相匹配的颜色。现在我想编辑关键字####到###*,#####到###**和######到###***,以便我可以轻松使用orgstruct-mode。有没有正则表达式方面的帮助?我尝试了以下内容:'(("^###\(* \)\([^#]。* \)$"(1'ess-jb-hide-face t)(2'ess-jb-h1-face t)) - stats-hb
@stats-hb 或许可以这样写?(未经测试):"^### \\(\\*\\)\\([^*].*\\)$" - juba
@juba 我已经使用你上面的代码一段时间来组织评论。我刚刚用emacs ess设置了一台新电脑,并且正在使用与我的旧电脑相同的init.el文件。然而,评论组织并没有起作用。我错过了什么?我需要安装一个包或其他东西吗?谢谢。 - Jacob

11

最近(2013年2月)对Orgmode的更新意味着您现在应该能够在源代码中嵌入org标题,并使用orgstruct-mode浏览它们。 因此,通过git升级您的org模式,然后尝试打开以下示例R文件。 当您位于包含嵌入式org标题的注释行上时,只需按TAB或shift-TAB,您就可以获得org模式标题。

### * Create data
data = list( s1=list(x=1:3, y=3:1), 
     s2=list(x=1:5, y=1:5), s3=list(x=1:4, y=rep(3,4)))

### * Base graphics version


par(mfrow=c(2,2))
lapply(data, plot)

### * Lattice version

nplots <- length(data)
pts.per.plot <- sapply(data, function(l) length(l$x))
df <- data.frame(which=rep(1:nplots, times=pts.per.plot),
                 x=unlist(sapply(data, function(l) l$x)),
                 y=unlist(sapply(data, function(l) l$y)))

xyplot(y~x|which, data=df, layout=c(2,2))

### ** Make the pdf
pdf(file='o.pdf')
xyplot(y~x|which, data=df, layout=c(2,1))                 
dev.off()

### * End of file

### Local Variables:
### eval: (orgstruct-mode 1)
### orgstruct-heading-prefix-regexp: "### "
### End:

嗯 - 我刚试了一下,但是没有反应?版本:Org-mode 版本 7.9.3e(7.9.3e-1123-g33d362 @ /home/rkrug/.emacs.d/org-mode/lisp/)。我应该在 org 邮件列表上询问吗? - Rainer
这对于我的大纲很有效,并且非常方便,但是标题没有显示特定的字体。你知道是否有这样的选项吗? - juba
我没有看到orgstruct中内置的任何东西可以进行额外的字体锁定,但是这里的另一个例子可以被改编为突出显示标题。 - Stephen Eglen
哇,这太棒了。根据层次结构更改颜色是可能的吗? - Veera

8
听起来你有一个庞大的分析脚本。这并不是很优化...
考虑使用RMarkdown或Sweave重新制作它,并使用knitr运行它。然后,您可以使用emacs的工具浏览markdown或TeX,并且您可以使用knitr中的缓存系统,以免在您接近结尾时更改某些内容时必须从头开始进行分析。
如果需要的话,您还可以得到一个格式化的分析报告。
此外,将东西分解为独立文件以进行源处理有点次优-编写函数并将其放入包中要好得多-并使用devtools包使其非常简单。只需编辑您的.R文件并使用load_all更新它(没有过去那些复杂的软件包构建问题)。
大赢家。

使用Rmarkdown的一个问题是它目前在Emacs/ESS中并没有得到真正的支持。 - Steve Lianoglou

3

Polymode 提供了 R+markdown、R+brew、R+cpp 和其他功能。它仍处于早期开发阶段,并且似乎只在最近的 Emacs (24.3) 上可靠地工作。


1

与上述 orgstruct-mode 类似,您还可以使用新的 outshine package,它与 outline-minor-mode 一起使用,将带星号的注释解释为类似 org-mode 的标题。它们可以使用简单的快捷键(如 TAB 等)折叠/展开/添加等。


0

另一个选择是allout-mode,这是我多年来一直很满意的选择。使用每个文件的本地变量:

## Local variables:
## allout-layout: (-1 : 0)
## End:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接