我有一些Rmd文档除了标题之外都有相同的YAML前缀。 如何将这个前置文件保存在一个文件中,并将其用于所有文档?它变得相当大,我不希望每次调整前端时都保持每个文件的步骤。< / p>
我还想
rstudio.markdownToHTML
(因为这需要我随身携带.Rprofile
)common.yaml:
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
# many other options
示例文档
----
title: On the Culinary Preferences of Anthropomorphic Cats
----
I do not like green eggs and ham. I do not like them, Sam I Am!
期望的输出:
已编译的示例文档(即HTML或PDF),已使用注入的common.yaml
中的元数据进行编译.YAML中的R代码(在本例中为日期)将被编译为奖励,但没有必要(我只把它用于我不需要的日期)。
我还没有完成任何这些工作。
_output.yaml
来放置常见的YAML元数据,但这会将所有元数据放在output:
下的YAML中,因此仅适用于html_document:
下的选项pdf_document:
,而不是像作者,日期等...... 编写一个knitr chunk来导入YAML,例如
----
title: On the Culinary Preferences of Anthropomorphic Cats
```{r echo=F, results='asis'}
cat(readLines('common.yaml'), sep='\n')
```
----
I do not like green eggs and ham. I do not like them, Sam I Am!
如果我knitr('input.Rmd')
然后pandoc
输出,这是有效的,但如果我使用Rstudio中的Knit按钮(我假设调用render
)则不行,因为这首先解析元数据在运行knitr之前,元数据格式错误,直到knitr运行。
common.yaml
注入input.Rmd
,然后运行rmarkdown::render()
,并以某种方式将它连接到Rstudio的Knit按钮,也许以某种方式将这个Rstudio配置保存到.Rproj
文件中,这样整个事情都是可移植的,我也不需要编辑.Rprofile
。但我不够聪明。编辑:我接受了最后一个选项并将Makefile连接到Build命令( Ctrl + Shift + 乙)。但是,每次我通过 Ctrl + Shift + B 使用它时,这将构建相同的目标,我想构建对应的目标使用我目前在编辑器中打开的Rmd文件[至于 Ctrl + Shift + K ]。
答案 0 :(得分:7)
找到了两个可移植的选项(即不需要.Rprofile
自定义,YAML前端的重复最少):
knit:
属性设置为您自己的函数,以便更好地控制Ctrl + Shift + K时发生的情况。将所有常见的YAML放在自己的文件中
common.yaml
:
---
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
---
请注意它是完整的,即需要---
。
然后在文档中你可以指定YAML作为pandoc的最后一个参数,它将应用YAML(参见this github issue)
example.rmd
中的:
---
title: On the Culinary Preferences of Anthropomorphic Cats
output:
html_document:
pandoc_args: './common.yaml'
---
I do not like green eggs and ham. I do not like them, Sam I Am!
您甚至可以将html_document:
内容放在_output.yaml
中,因为rmarkdown
会将output:
放在knit
下,以便该文件夹中的所有文档都可以使用knit
。通过这种方式,使用此前端的所有文档之间可能存在无重复YAML。
<强>优点:强>
<强>缺点:强>
knit:
,因此不会解析上面的日期字段。您将获得文字字符串“r format(Sys.time(),format ='%Y-%m-%d%H:%M:%S%z')”作为您的日期。:
首先看到的元数据定义保持不变,即使稍后解析冲突的数据也是如此。
根据您的设置,这可能会在某些时候出现问题。
myknit(inputFile, encoding)
命令这允许更大的控制,但有点麻烦/棘手。
This link和this one在rmarkdown中提到了一个未记录的功能:当点击Rstudio的“Knit”按钮时,将执行YAML的render
部分。
简而言之:
myknit.r
,它将读取YAML,将其放入RMD并在结果上调用example.rmd
。保存在自己的文件 knit: (function (...) { source('myknit.r'); myknit(...) })
。在source('myknit.r')
的YAML中,添加
myknit.r
似乎必须在一条线上。 knit
而不是仅仅将函数定义放在YAML中的原因是为了便于携带。如果我修改common.yaml
,我不必修改每个文档的YAML。这样,所有文档必须在其前端重复的唯一 common YAML是myknit
行;所有其他常见的YAML都可以留在make
。
然后按Ctrl + Shift + K按照我希望的方式在Rstudio中工作。
补充说明:
rmarkdown
可能只是对render
的系统调用。myknit
并因此编织,因为在<{1}}的调用之前注入。预览窗口:只要Output created: path/to/file.html
生成(单个)消息render
,该文件就会显示在预览窗口中。
我发现输出中只有一个这样的消息[不是多个],或者你没有预览窗口。因此,如果您使用render(..., quiet=T)
(生成“输出已创建:basename.extension”)消息并且最终生成的文件实际上位于其他位置,则需要通过suppressMessages(render(...))
或{{1来禁止此消息(前者也抑制了knitr进程和pandoc输出),并使用正确的路径创建自己的消息。
<强>优点:强>
<强>缺点:强>
knit:
行必须在每个文档中重复(尽管source('./myknit.r')
至少函数定义可以存储在一个中心位置)这是后人的设置。为了便于携带,您只需随身携带myknit.r
和common.yaml
。不需要.Rprofile
或项目特定的配置。
example.rmd
:
---
title: On the Culinary Preferences of Anthropomorphic Cats
knit: (function (...) { source('myknit.r'); myknit(...) })
---
I do not like green eggs and ham. I do not like them, Sam I Am!
common.yaml
[例如]:
author: me
date: "`r format (Sys.time(), format='%Y-%m-%d %H:%M:%S %z')`"
link-citations: true
reference-section-title: References
myknit.r
:
myknit <- function (inputFile, encoding, yaml='common.yaml') {
# read in the YAML + src file
yaml <- readLines(yaml)
rmd <- readLines(inputFile)
# insert the YAML in after the first ---
# I'm assuming all my RMDs have properly-formed YAML and that the first
# occurence of --- starts the YAML. You could do proper validation if you wanted.
yamlHeader <- grep('^---$', rmd)[1]
# put the yaml in
rmd <- append(rmd, yaml, after=yamlHeader)
# write out to a temp file
ofile <- file.path(tempdir(), basename(inputFile))
writeLines(rmd, ofile)
# render with rmarkdown.
message(ofile)
ofile <- rmarkdown::render(ofile, encoding=encoding, envir=new.env())
# copy back to the current directory.
file.copy(ofile, file.path(dirname(inputFile), basename(ofile)), overwrite=T)
}
从example.rmd
的编辑器按Ctrl + Shift + K / Knit将编译结果并显示预览。我知道它正在使用common.yaml
,因为结果包含日期和作者,而example.rmd
本身没有日期或作者。
答案 1 :(得分:0)
@mathematical.coffee提出的第一个解决方案是一种很好的方法,但是它给出的示例对我而言不起作用(可能是因为语法已更改)。如此说来,这可以通过在YAML标头中提供pandoc参数来实现。例如,
这是header.yaml
文件的内容:
title: "Crime and Punishment"
author: "Fyodor Dostoevsky"
将此添加到RMarkdown文件的开头:
---
output:
html_document:
pandoc_args: ["--metadata-file=header.yaml"]
---
See the pandoc manual作为--metadata-file
参数。