我认为这是一个很常见的问题,关于优化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)
通过这种方式,可以生成与绘图具有相同文件名的文本文件,其中的信息可以帮助确定绘图的生成方式和位置。
答案 0 :(得分:2)
有一个名为Project Template的软件包可以帮助组织和自动化典型的工作流程,包括R脚本,数据文件,图表等。还有许多有用的文档,例如Workflow of statistical data analysis by Oliver Kirchkamp。
如果您使用Emacs和ESS进行分析,则必须学习Org-Mode。我用它来组织我的所有工作。以下是它与R集成的方式:R Source Code Blocks in Org Mode。
还有一个名为Drake的新免费工具,它被宣传为“make for data”。
答案 1 :(得分:1)
就一般R组织而言:我喜欢使用单个脚本来重新创建项目的所有工作。任何项目都应该只需单击即可重现,包括与该项目相关的所有图表或论文。
因此,要保持井井有条:为每个项目保留一个不同的目录,每个项目都有自己的函数.R脚本存储与该项目关联的非包函数,每个项目都有一个像
## myproject
source("functions.R")
source("read-data.R")
source("clean-data.R")
等等......一路走来。这应该有助于保持一切井然有序,如果您获得新数据,您只需转到早期脚本来修复标题或其他内容,只需单击一下即可重新运行整个项目。
答案 2 :(得分:1)
我认为我的问题掩盖了一定程度的混乱。环顾四周,并探讨了迄今为止提供的建议,我得出的结论是,知道文件的生成位置和方式可能并不重要。实际上,您应该能够消除任何输出,并通过重新运行代码来重现它。因此,虽然我仍然可以使用上述功能获取额外信息,但实际上这是一个无情的问题,并且确实偶尔会清理文件夹。这些想法更加雄辩地解释here。这当然不排除使用Make / Drake或Project Template,我将尽力接受。再次感谢@noah和@alex的建议!
答案 3 :(得分:0)
现在还有一个R package called drake(R中的数据框为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
。)
答案 4 :(得分:0)
RStudio 开发了一个名为 pins 的软件包可以解决这个问题。