在R工作流程中编写函数与逐行解释

low*_*rul 10 statistics workflow r

这里已经写了很多关于在R中为统计项目开发工作流程的文章.最受欢迎的工作流程似乎是Josh Reich的LCFD模型.使用main.R包含代码:

source('load.R')
source('clean.R')
source('func.R')
source('do.R')
Run Code Online (Sandbox Code Playgroud)

这样一个单独source('main.R')运行整个项目.

问:是否有一个理由,更喜欢这个工作流程的一个该行由行解释工作做的load.R,clean.R以及do.R是由被调用的函数代替main.R

我现在找不到这个链接了,但是我已经在某个地方看过,当在R中编程时,必须克服他们用函数调用来编写所有内容的愿望 - 这就是R代表写的是这个行 - 解释形式.

问:真的吗?为什么?

我对LCFD方法感到沮丧,我可能会根据函数调用编写所有内容.但在此之前,我想听听SO的优秀人士是否这是一个好主意.

编辑:我正在进行的项目是(1)读取一组财务数据,(2)清理它(非常复杂),(3)使用我的估算器估算与数据相关的一些数量(4)使用传统估算器估算相同数量(5)报告结果.我的程序应该以这样的方式编写,即对于不同的经验数据集(1)进行模拟数据,或(3)使用不同的估计器,这是一项工作(1).此外,它应该遵循有文化的编程和可重复的研究指南,以便新的代码运行程序,了解正在发生的事情,以及如何调整它.

Spa*_*man 15

我认为源文件中创建的任何临时内容都不会被清除.如果我做:

x=matrix(runif(big^2),big,big)
z=sum(x)
Run Code Online (Sandbox Code Playgroud)

并且作为一个文件,x虽然我不需要它,但它仍然存在.但如果我这样做:

ff=function(big){
 x = matrix(runif(big^2),big,big)
 z=sum(x)
 return(z)
}
Run Code Online (Sandbox Code Playgroud)

而不是源代码,在我的脚本中执行z = ff(big),x矩阵超出范围,因此得到清理.

功能可以实现简单的可重复使用的封装,并且不会在外部污染.一般来说,它们没有副作用.您的逐行脚本可能正在使用与当前使用的数据集绑定的全局变量和名称,这使它们无法使用.

我有时会逐行工作,但是当我得到超过大约五行时,我发现我真正需要的是一个适当的可重用功能,而且我经常会最终重新使用它.


G. *_*eck 13

我认为没有一个答案.最好的办法是记住相对优点,然后选择适合这种情况的方法.

1)功能.不使用函数的优点是所有变量都保留在工作区中,您可以在最后检查它们.这可能会帮助您弄清楚如果您遇到问题会发生什么.

另一方面,精心设计的功能的优点是您可以对它们进行单元测试.也就是说,您可以将它们与其他代码区分开来,使它们更容易测试.此外,当你使用一个函数,模拟某些低级构造时,你知道一个函数的结果不会影响其他函数,除非它们被传递掉,这可能会限制一个函数的错误处理对另一个函数的损害.您可以使用debugR中的工具来调试您的功能,并且能够单步执行它们是一个优势.

2)LCFD.关于是否应该使用load/clean/func/do的分解,无论它是通过执行source还是函数是第二个问题.这种分解的问题无论是完成通过source还是函数,都需要运行一个只是为了能够测试下一个,所以你不能真正独立地测试它们.从这个角度来看,它不是理想的结构.

另一方面,它的优势在于,如果您想在不同的数据上进行尝试,您可以独立于其他步骤替换加载步骤,并且如果您需要,可以独立于加载和清洁步骤替换其他步骤尝试不同的处理.

3)文件数可能存在第三个问题隐含在您询问是否所有内容都应该在一个或多个源文件中.将东西放在不同的源文件中的好处是您不必查看不相关的项目.特别是如果你有一些没有被使用或与当前函数无关的例程,你会看到它们不会中断流程,因为你可以安排它们在其他文件中.

另一方面,从(a)部署的角度来看,将所有内容放在一个文件中可能是有利的,即您可以向某人发送单个文件,以及(b)编辑方便,因为您可以将整个程序放入单个编辑器会话,例如,便于搜索,因为您可以使用编辑器的功能搜索整个程序,因为您不必确定例程所在的文件.此外,连续的撤消命令将允许您向后移动所有单元您的程序和单个保存将保存所有模块的当前状态,因为只有一个.(c)速度,即如果你在慢速网络上工作,将一个文件保存在本地机器中然后偶尔写出来而不是必须来回慢速遥控器可能会更快.

注意:另一件需要考虑的事情是,使用软件包可能比首先采购文件更适合您的需求.


had*_*ley 7

在编写函数时没有人提到一个重要的考虑因素:除非你一次又一次地重复某些动作,否则编写它们没有多大意义.在分析的某些部分,您将进行一次性操作,因此为它们编写函数没有多大意义.如果你不得不重复几次,那么值得投入时间和精力来编写一个可重复使用的功能.


Bra*_*sen 6

工作流程:

我用的东西很相似:

  1. Base.r:拉取主数据,调用其他文件(第2到第5项)
  2. Functions.r:加载函数
  3. Plot Options.r:加载我经常使用的一些常规绘图选项
  4. Lists.r:加载列表,我有很多,因为公司名称,语句等随着时间的推移而变化
  5. Recodes.r:大部分工作都在这个文件中完成,基本上是数据清理和排序

到目前为止还没有进行任何分析.这仅用于数据清理和排序.

在Recodes.r结束时,我保存环境以重新加载到我的实际分析中.

save(list=ls(), file="Cleaned.Rdata")
Run Code Online (Sandbox Code Playgroud)

完成清洁,功能和绘图选项后,我开始进入分析.同样,我继续将其分解为专注于主题或主题的较小文件,例如:人口统计,客户请求,相关性,对应分析,情节等.我几乎总是自动运行前5个来设置我的环境,然后我逐行运行其他的以确保准确性和探索.

在每个文件的开头,我加载清理的数据环境并繁荣.

load("Cleaned.Rdata")
Run Code Online (Sandbox Code Playgroud)

对象命名法:

我不使用列表,但我确实使用了命名法来表示我的对象.

df.YYYY # Data for a certain year
demo.describe.YYYY ## Demographic data for a certain year
po.describe ## Plot option
list.describe.YYYY ## lists
f.describe ## Functions
Run Code Online (Sandbox Code Playgroud)

使用友好的助记符替换上面的"描述".

评论

我一直试图让自己养成使用评论(x)的习惯,我发现它非常有用.代码中的注释很有帮助,但通常不够.

打扫干净

同样,在这里,我总是尝试使用相同的对象进行简单的清理.例如tmp,tmp1,tmp2,tmp3,并确保在结束时删除它们.

功能

其他帖子中有一些评论,如果你不止一次地使用它,只会写一些函数.我想调整一下来说,如果你认为你有可能再次使用它,你应该把它扔进一个函数中.我甚至无法计算我希望为逐行创建的流程编写函数的次数.

此外,在我更改一个函数之前,我将它抛入一个名为Deprecated Functions.r的文件中,再次防止"我该怎么做"这个效果.