当我进行任何复杂的R项目时,我的脚本很快就会变得冗长而混乱。
我可以采用哪些实践来使我的代码始终令人愉快?我在考虑类似
- 函数在源文件中的放置
- 何时将内容分解到另一个源文件
- 主文件中应包含什么
- 将功能用作组织单位(鉴于R使其难以访问全局状态,这是否值得)
- 缩进/换行的做法。
- 对待(如{?
- 将}}之类的内容放在1或2行上?
基本上,组织大型R脚本的经验法则是什么?
ProjectTemplate
包装。
当我进行任何复杂的R项目时,我的脚本很快就会变得冗长而混乱。
我可以采用哪些实践来使我的代码始终令人愉快?我在考虑类似
基本上,组织大型R脚本的经验法则是什么?
ProjectTemplate
包装。
Answers:
标准答案是使用软件包-请参阅《编写R扩展》手册以及网络上的其他教程。
它给你
R CMD check
仅运行source()
代码即可处理非常短的代码段。其他所有内容都应放在程序包中-即使您不打算发布它,因为您可以为内部存储库编写内部程序包。
至于“如何编辑”部分,R Internals手册在第6节中具有出色的R编码标准。否则,我倾向于在Emacs的ESS模式下使用默认值。
更新时间2008年8月13日: David Smith刚刚写了有关Google R样式指南的博客。
我喜欢将不同的功能放在自己的文件中。
但是我不喜欢R的包装系统。很难使用。
我更喜欢轻量级的选择,将文件的功能放在环境中(其他每种语言都称为“命名空间”)并附加它。例如,我制作了一组“ util”函数,如下所示:
util = new.env()
util$bgrep = function [...]
util$timeit = function [...]
while("util" %in% search())
detach("util")
attach(util)
所有这些都在util.R文件中。当您获取它时,您将获得环境“ util”,因此可以进行调用util$bgrep()
等。但是此外,该attach()
呼叫使它变得公正bgrep()
而直接。如果您不将所有这些函数放在自己的环境中,则它们会污染解释器的顶级名称空间(ls()
显示的名称空间)。
我试图模拟Python的系统,其中每个文件都是一个模块。那样会更好,但这似乎还可以。
sys.source
:MyEnv <- attach(NULL, name=s_env); sys.source(file, MyEnv)
。我什至在启动时声明了(在其自己的环境中!)一个函数sys.source2
,该函数将查找是否已经存在相同名称的环境,并提供给这个环境而不是创建一个新环境。它可以快速,轻松且有条理地添加个人功能:-)
这听起来似乎有点明显,尤其是如果您是一名程序员,但是这就是我对逻辑和物理代码单元的看法。
我不知道这是否是您的情况,但是当我在R中工作时,我很少想到一个大型的复杂程序。我通常从一个脚本开始,然后通常使用函数将代码分成逻辑上可分离的单元。数据操作和可视化代码放置在它们自己的功能中,等等。这些功能在文件的一个部分中分组在一起(数据操作在顶部,然后是可视化,等等)。最终,您需要考虑如何使维护脚本和降低缺陷率变得更容易。
您使函数执行的精细度/粗略度会有所不同,并且有各种经验法则:例如15行代码,或“一个功能应负责执行由其名称标识的一项任务”,等等。您的里程会有所不同。由于R不支持按引用调用,因此在涉及传递数据帧或类似结构时,我通常会使我的函数粒度过于细微。但是,当我刚开始使用R时,这可能会补偿一些愚蠢的性能错误。
何时将逻辑单元提取到自己的物理单元(例如源文件和更大的分组(如包))中?我有两种情况。首先,如果文件太大,并且在逻辑上无关的单位之间滚动会很麻烦。第二,如果我具有可以被其他程序重用的功能。我通常首先将一些分组的单元(例如数据操作函数)放入一个单独的文件中。然后,我可以从任何其他脚本中获取该文件。
如果要部署功能,则需要开始考虑软件包。由于各种原因,我不会在生产中部署R代码,也不会将其部署给其他人使用(简而言之:组织文化更喜欢其他语言,对性能的关注,GPL等)。另外,我倾向于不断地完善并添加到我的源文件集合中,而当我进行更改时,我宁愿不处理软件包。因此,您应该查看其他与软件包相关的答案,例如Dirk的答案,以获取有关此方面的更多详细信息。
最后,我认为您的问题并不一定是R所特有的。我真的建议阅读Steve McConnell撰写的Code Complete,其中包含有关此类问题和整个编码实践的很多知识。
我一直想弄清楚如何编写包,但没有花时间。对于我的每个微型项目,我都将所有低层函数保存在一个名为“ functions /”的文件夹中,并将它们提供给我明确创建的单独命名空间。
以下代码行将在搜索路径上创建一个名为“ myfuncs”的环境(如果尚不存在)(使用附加),并使用“ functions /”目录中.r文件中包含的功能填充它(使用sys.source)。我通常将这些行放在用于“用户界面”的主脚本的顶部,从中可以调用高级功能(调用低级功能)。
if( length(grep("^myfuncs$",search()))==0 )
attach("myfuncs",pos=2)
for( f in list.files("functions","\\.r$",full=TRUE) )
sys.source(f,pos.to.env(grep("^myfuncs$",search())))
进行更改时,您始终可以使用相同的行来重新获得它,或使用类似
evalq(f <- function(x) x * 2, pos.to.env(grep("^myfuncs$",search())))
在您创建的环境中评估添加/修改。
我知道这很笨拙,但避免对此过于正式(但是如果您有机会,我会鼓励打包系统-希望将来会以这种方式迁移)。
至于编码约定,这是我唯一见过的关于美学的东西(我喜欢它们,并且不拘一格,但我在R中没有使用太多花括号):
http://www1.maths.lth.se/help/R/RCC/
关于use [,drop = FALSE]和<-的其他“约定”,在useR的各种演示文稿(通常是主题演讲)中建议使用!会议,但我认为这些都不是严格的(尽管[,drop = FALSE]对于不确定您期望输入的程序很有用)。
还没有学会如何编写软件包,我一直通过寻找子脚本来组织工作。它类似于编写类,但不涉及编写类。它在编程上不尽人意,但随着时间的流逝,我发现我会进行分析。一旦有了一个很大的部分可以工作,我经常将其移至其他脚本并仅提供其源代码,因为它将使用工作区对象。也许我需要从多个来源导入数据,对所有数据进行排序并找到交叉点。我可以将该部分放入其他脚本中。但是,如果您想将“应用程序”分发给其他人,或者使用一些交互式输入,则打包可能是一个不错的选择。作为研究人员,我很少需要分发我的分析代码,但是我经常需要对它进行扩充或调整。
我也一直在寻找正确的工作流程,以完成一个R大项目。去年,我发现了这个名为rsuite的软件包,当然,这正是我想要的。这个R包是为部署大型R项目而明确开发的,但是我发现它可以用于较小,中等大小和大型R项目。我将在一分钟内(下)提供指向真实示例的链接,但首先,我想解释用来构建R项目的新范例rsuite
。
注意。我不是的创建者或开发者rsuite
。
我们一直在用RStudio进行所有错误的项目。目标不应该是创建项目或程序包,而应该是更大的范围。在rsuite中,您将创建一个超级项目或主项目,其中包含标准的R项目和R包,并且可能存在所有组合。
通过拥有一个R超级项目,您不再需要Unix make
来管理下面的R项目的较低级别。您在顶部使用R脚本。让我给你演示。创建rsuite主项目时,将获得以下文件夹结构:
该文件夹R
是放置项目管理脚本的位置,该脚本将替换make
。
该文件夹packages
是rsuite
存放组成超级项目的所有软件包的文件夹。您也可以复制粘贴无法从Internet访问的软件包,rsuite也会进行构建。
该文件夹deployment
就是rsuite
会写了指示的包,该包的所有二进制DESCRIPTION
文件。因此,这本身就使您可以计划完全可复制的加速时间。
rsuite
带有所有操作系统的客户端。我已经测试了所有。但是您也可以将其安装addin
为RStudio。
rsuite
还可以让您conda
在其自己的文件夹中构建隔离的安装conda
。这不是环境,而是从计算机上的Anaconda派生的物理Python安装。这可以与R一起使用SystemRequirements
,从中可以从所需的任何conda通道安装所需的所有Python软件包。
您还可以创建本地存储库,以在脱机时提取R软件包,或者希望更快地构建整个软件包。
如果需要,您还可以将R项目构建为zip文件并与同事共享。只要您的同事安装了相同的R版本,它将运行。
另一个选择是在Ubuntu,Debian或CentOS中构建整个项目的容器。因此,您无需与项目构建共享一个zip文件,而是Docker
与准备运行的项目共享整个容器。
我一直在尝试rsuite
寻找完全的可重复性,并避免依赖于在全局环境中安装的软件包。这是错误的,因为一旦您安装了软件包更新,项目通常就会停止工作,特别是那些对具有某些参数的函数进行非常特定调用的软件包。
我开始尝试的第一件事是使用bookdown
电子书。我从来没有足够幸运地拥有一本可以经受住六个月以上时间考验的书。因此,我所做的就是转换原始的书本项目以遵循该rsuite
框架。现在,我不必担心更新我的全局R环境,因为该项目在deployment
文件夹中有自己的一组软件包。
我要做的第二件事是创建机器学习项目,但是rsuite
顺便说一下。一个主要的,协调的项目在顶部,所有子项目和程序包都在该部分的控制之下。它确实改变了您使用R进行编码的方式,从而提高了工作效率。
之后,我开始在一个名为的新软件包中工作rTorch
。之所以可能这样做,很大程度上是因为rsuite
; 它使您能够思考并不断壮大。
一条建议。学习rsuite
并不容易。因为它提供了创建R项目的新方法,所以很难。初次尝试时不要惊慌,继续爬上斜坡,直到爬上为止。它需要您的操作系统和文件系统的高级知识。
我希望有一天RStudio
,我们可以像rsuite
从菜单中一样生成编排项目。这一定非常棒。
链接:
R可以用于交互式和小型脚本,但我不会将其用于大型程序。我会在大多数编程中使用主流语言,并将其包装在R接口中。
Rcpp
程序包(包括R程序中的C ++代码)变得非常简单。因此,重写R代码的某些部分可以很容易地集成到R中。此外,RStudio的问世引入了R的IDE,尽管可能还不如Visual Studio强大。