所以经常在那里我一个主要研发降价文件或knitr乳胶文件source
一些其他R档(例如,用于数据处理)。 然而,我在想,在某些情况下,这将是有益的,这些源文件是自己的重现性文件(如,的R降价文件,该文件不仅包括用于数据处理的命令,而且还产生了可重复的文件,说明数据处理决定)。
因此,我希望有这样的命令source('myfile.rmd')
在我的主要研发减价文件。 将提取和源极中的R代码块内所有的R代码myfile.rmd
。 当然,这产生了一个错误。
下面的命令作品:
```{r message=FALSE, results='hide'}
knit('myfile.rmd', tangle=TRUE)
source('myfile.R')
```
其中results='hide'
,如果输出被需要,可以省略。 即,从knitr输出的R代码myfile.rmd
成myfile.R
。
然而,这似乎并不完美:
- 这将导致创建一个额外的文件
- 它需要如果需要在显示控制出现在它自己的代码块。
- 这不是那么简单,优雅
source(...)
因此,我的问题: 是否有采购的R降价文件中的R代码的一个更优雅的方式?
看来你正在寻找一个班轮。 如何把这个在你的.Rprofile
?
ksource <- function(x, ...) {
library(knitr)
source(purl(x, output = tempfile()), ...)
}
不过,我不明白你为什么要source()
在RMD代码文件本身。 我的意思是knit()
将运行该文件中的所有代码,如果你提取代码,并在一大块运行它,所有的代码都需要进行两次当您运行knit()
这个文件(你自己跑自己的内部)。 这两个任务应该是分开的。
如果你真的想运行的所有代码,RStudio使这相当容易: Ctrl + Shift + R
。 它基本上调用purl()
和source()
幕后。
出因子共同的代码放到一个单独的R档,然后来源,R档到每个RMD文件要进去。
因此,例如,假设我有两个报告,我需要做,流感爆发和枪VS黄油分析。 当然,我会创建两个RMD文件,并用它做。
现在假定老板走来并希望看到流感爆发的与黄油的价格变化(在控制9毫米弹药)。
- 复制和粘贴代码分析报告,进入新的报告是代码重用,等一个坏主意
- 我希望它看起来美观大方。
我的解决办法是因素的项目到这些文件:
- Flu.Rmd
- Guns_N_Butter.Rmd
- guns_data_import.R
- butter_data_import.R
每个RMD文件中我有这样的:
```{r include=FALSE}
source('flu_data_import.R')
```
这里的问题是,我们失去的重现性。 我对此的解决方案是创建一个共同的子文档,包括到每个RMD文件。 因此,在我创建的每一个RMD文件的末尾,我补充一点:
```{r autodoc, child='autodoc.Rmd', eval=TRUE}
```
而且,当然,autodoc.Rmd:
Source Data & Code
----------------------------
<div id="accordion-start"></div>
```{r sourcedata, echo=FALSE, results='asis', warnings=FALSE}
if(!exists(autodoc.skip.df)) {
autodoc.skip.df <- list()
}
#Generate the following table:
for (i in ls(.GlobalEnv)) {
if(!i %in% autodoc.skip.df) {
itm <- tryCatch(get(i), error=function(e) NA )
if(typeof(itm)=="list") {
if(is.data.frame(itm)) {
cat(sprintf("### %s\n", i))
print(xtable(itm), type="html", include.rownames=FALSE, html.table.attributes=sprintf("class='exportable' id='%s'", i))
}
}
}
}
```
### Source Code
```{r allsource, echo=FALSE, results='asis', warning=FALSE, cache=FALSE}
fns <- unique(c(compact(llply(.data=llply(.data=ls(all.names=TRUE), .fun=function(x) {a<-get(x); c(normalizePath(getSrcDirectory(a)),getSrcFilename(a))}), .fun=function(x) { if(length(x)>0) { x } } )), llply(names(sourced), function(x) c(normalizePath(dirname(x)), basename(x)))))
for (itm in fns) {
cat(sprintf("#### %s\n", itm[2]))
cat("\n```{r eval=FALSE}\n")
cat(paste(tryCatch(readLines(file.path(itm[1], itm[2])), error=function(e) sprintf("Could not read source file named %s", file.path(itm[1], itm[2]))), sep="\n", collapse="\n"))
cat("\n```\n")
}
```
<div id="accordion-stop"></div>
<script type="text/javascript">
```{r jqueryinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://code.jquery.com/jquery-1.9.1.min.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r tablesorterinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://tablesorter.com/__jquery.tablesorter.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r jqueryuiinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://code.jquery.com/ui/1.10.2/jquery-ui.min.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r table2csvinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(file.path(jspath, "table2csv.js")), sep="\n")
```
</script>
<script type="text/javascript">
$(document).ready(function() {
$('tr').has('th').wrap('<thead></thead>');
$('table').each(function() { $('thead', this).prependTo(this); } );
$('table').addClass('tablesorter');$('table').tablesorter();});
//need to put this before the accordion stuff because the panels being hidden makes table2csv return null data
$('table.exportable').each(function() {$(this).after('<a download="' + $(this).attr('id') + '.csv" href="data:application/csv;charset=utf-8,'+encodeURIComponent($(this).table2CSV({delivery:'value'}))+'">Download '+$(this).attr('id')+'</a>')});
$('#accordion-start').nextUntil('#accordion-stop').wrapAll("<div id='accordion'></div>");
$('#accordion > h3').each(function() { $(this).nextUntil('h3').wrapAll("<div>"); });
$( '#accordion' ).accordion({ heightStyle: "content", collapsible: true, active: false });
</script>
NB,这是专为RMD - > HTML工作流程。 这将是一个丑陋的烂摊子,如果你用乳胶或其他任何东西去。 该RMD文档看起来通过全球环境的所有源()“执行的文件,包括在你的文档的末尾它们的来源。 它包括jQuery UI的,的tablesorter,并设置文件为使用手风琴式的显示/隐藏源文件。 它的工作正在进行中,但随时以使其适应自己的用途。
不是一班轮,我知道了。 希望它给你一些想法至少:)
也许人们应该开始思考不同。 我的问题是这样的:写的每一个你通常将不得不在一个.R文件.Rmd块码。 而对于使用编织即一个html的文件RMD,你只离开
```{R Chunkname, Chunkoptions}
source(file.R)
```
这样,你可能会创建一堆.R文件,你失去处理所有代码“大块大块后”使用CTRL + ALT + n的优势(或+ C,但通常这不工作)。 但是,我读到甘拉德先生的书约重复性的研究和认识,那他肯定使用knitr和.Rmd文件只用于创建HTML文件。 主要分析本身就是一个.R文件。 我认为,如果你开始做里面你的整个分析.Rmd文档快速增长过大。
下面的技巧为我工作得很好:
library(readr)
library(stringr)
source_rmd <- function(file_path) {
stopifnot(is.character(file_path) && length(file_path) == 1)
.tmpfile <- tempfile(fileext = ".R")
.con <- file(.tmpfile)
on.exit(close(.con))
full_rmd <- read_file(file_path)
codes <- str_match_all(string = full_rmd, pattern = "```(?s)\\{r[^{}]*\\}\\s*\\n(.*?)```")
stopifnot(length(codes) == 1 && ncol(codes[[1]]) == 2)
codes <- paste(codes[[1]][, 2], collapse = "\n")
writeLines(codes, .con)
flush(.con)
cat(sprintf("R code extracted to tempfile: %s\nSourcing tempfile...", .tmpfile))
source(.tmpfile)
}
我会建议保持在.R文件主要分析和计算代码,并导入块根据需要.Rmd文件。 我已经解释的过程在这里 。