3

关于优化 R 中的工作流程,我有一个我认为很常见的问题。具体来说,我怎样才能避免文件夹中充满输出(绘图、RData 文件、csv 等)的常见问题,而在一段时间后没有,知道它们来自哪里或它们是如何产生的吗?在某种程度上,它肯定涉及尝试对文件夹结构进行智能处理。我一直在环顾四周,但我不确定最好的策略是什么。到目前为止,我已经以一种相当简单(矫枉过正)的方式解决了它:我创建了一个函数metainfo(见下文),它使用给定的文件名写入带有元数据的文本文件。想法是,如果生成了绘图,则发出此命令以生成与绘图完全相同的文件名的文本文件(当然,扩展名除外),其中包含有关系统、会话、加载的包、R 的信息调用元数据函数的版本、函数和文件等。问题是:

(i) 人们如何处理这个普遍的问题?有没有明显的方法可以避免我提到的问题?

(ii) 如果没有,是否有人对改进此功能有任何提示?目前它可能很笨重而且不理想。特别是,获取生成绘图的文件名不一定有效(我使用的解决方案是 @hadley 在1中提供的解决方案)。欢迎任何想法!

该函数假定为 git,因此请忽略可能产生的警告。这是主要功能,存储在文件中metainfo.R

MetaInfo <- function(message=NULL, filename)
{
  # message  - character string - Any message to be written into the information
  #            file (e.g., data used).
  # filename - character string - the name of the txt file (including relative
  #            path). Should be the same as the output file it describes (RData,
  #            csv, pdf).
  #

  if (is.null(filename))
  {
    stop('Provide an output filename - parameter filename.')
  }

  filename <- paste(filename, '.txt', sep='')

  # Try to get as close as possible to getting the file name from which the
  # function is called.
  source.file <- lapply(sys.frames(), function(x) x$ofile)
  source.file <- Filter(Negate(is.null), source.file)
  t.sf <- try(source.file <- basename(source.file[[length(source.file)]]),
              silent=TRUE)

  if (class(t.sf) == 'try-error')
  {
    source.file <- NULL
  }

  func <- deparse(sys.call(-1)) 

  # MetaInfo isn't always called from within another function, so func could
  # return as NULL or as general environment.
  if (any(grepl('eval', func, ignore.case=TRUE)))
  {
    func <- NULL
  }

  time    <- strftime(Sys.time(), "%Y/%m/%d %H:%M:%S")
  git.h   <- system('git log --pretty=format:"%h" -n 1', intern=TRUE)
  meta <- list(Message=message,
               Source=paste(source.file, ' on ', time, sep=''),
               Functions=func,
               System=Sys.info(),
               Session=sessionInfo(),
               Git.hash=git.h)
  sink(file=filename)
  print(meta)
  sink(file=NULL)
}

然后可以在另一个函数中调用它,存储在另一个文件中,例如:

source('metainfo.R')

RandomPlot <- function(x, y)
{
  fn <- 'random_plot'
  pdf(file=paste(fn, '.pdf', sep=''))
  plot(x, y)
  MetaInfo(message=NULL, filename=fn)
  dev.off()
}

x <- 1:10
y <- runif(10)

RandomPlot(x, y)

这样,将生成一个与绘图具有相同文件名的文本文件,其中的信息有望帮助确定绘图的生成方式和位置。

4

5 回答 5

2

有一个名为Project Template的包,它帮助组织和自动化使用 R 脚本、数据文件、图表等的典型工作流。还有许多有用的文档,比如Oliver Kirchkamp 的统计数据分析工作流

如果您使用 Emacs 和 ESS 进行分析,那么学习Org-Mode是必须的。我用它来组织我所有的工作。以下是它与 R 的集成方式:Org Mode 中的 R 源代码块

还有一个名为Drake的新免费工具,它被宣传为“为数据而制造”。

于 2013-05-31T19:38:05.580 回答
2

就一般的 R 组织而言:我喜欢有一个脚本来重新创建为项目完成的所有工作。任何项目都应该可以通过单击来重现,包括与该项目相关的所有图或论文。

因此,为了保持井井有条:为每个项目保留不同的目录,每个项目都有自己的函数。R 脚本用于存储与该项目关联的非包函数,并且每个项目都有一个主脚本,其开头类似于

## myproject
source("functions.R")
source("read-data.R")
source("clean-data.R")

等等……一直到。这应该有助于保持一切井井有条,如果您获得新数据,您只需转到早期脚本来修复标题或其他任何内容,然后单击即可重新运行整个项目。

于 2013-05-31T19:31:07.203 回答
1

I think my question belies a certain level of confusion. Having looked around, as well as explored the suggestions provided so far, I have reached the conclusion that it is probably not important to know where and how a file is produced. You should in fact be able to wipe out any output, and reproduce it by rerunning code. So while I might still use the above function for extra information, it really is a question of being ruthless and indeed cleaning up folders every now and then. These ideas are more eloquently explained here. This of course does not preclude the use of Make/Drake or Project Template, which I will try to pick up on. Thanks again for the suggestions @noah and @alex!

于 2013-06-04T09:41:17.513 回答
0

现在还有一个名为 drake 的 R 包(R 中的 Data Frames for Make),独立于 Factual 的 Drake。R 包也是一个类似于 Make 的构建系统,它将代码/依赖项与输出链接起来。

install.packages("drake") # It is on CRAN.
library(drake)
load_basic_example()
plot_graph(my_plan)
make(my_plan)

就像它的前身remake一样,它还有一个额外的好处,就是您不必跟踪一堆繁琐的文件。在 R 中生成的对象在过程中被缓存make()并且可以很容易地重新加载。

readd(summ_regression1_small) # Read objects from the cache.
loadd(small, large) # Load objects into your R session.
print(small)

但是您仍然可以将文件用作单引号目标。(参见基本示例中的'report.Rmd'和。)'report.md'my_plan

于 2017-09-15T12:26:04.037 回答
0

RStudio 开发了一个名为pin的包,可以解决这个问题。

于 2021-04-16T08:59:15.860 回答