使用 knitr,在将块放入单独的文件时保留块选项
With knitr, preserve chunk options when purling chunks into separate files
出于教学目的,我想 purl
我的 .Rnw
文件的块分成单独的文件。这个答案解释了如何去做:
How to purl each chunks in .Rmd file to multiple .R files using Knitr
但是该方法不保留块选项。由于我生成的块会生成图,因此保留 fig.width
和 fig.height
选项很重要。理想情况下,我想要一个看起来像这样的块:
<<plot, fig.width = 3, fig.height = 5, outwidth = '.75\textwidth'>>=
plot (1,1)
@
成为一个名为 plot.R
的文件,如下所示:
#+ fig.width = 3, fig.height = 5
plot (1,1)
也就是把块选项fig.width
和fig.height
变成spin()
可以识别的格式,就像purl()
一样,去掉不相关的块选项,或者为 spin()
到 Word 中创建问题,例如 out.width
。本着创建用户友好的代码文件的精神。
由于您引用的答案没有从 purl
的结果中复制 header 行,因此您丢失了除块名称之外的所有内容。虽然您可以调整它以粘贴到 header 中,但实际上构建一个函数来解析 purl
的输出并不难——比尝试解析 Rmd
或 [= 容易得多14=] 文档,无论如何,比弄清楚 knitr
是如何做到的更容易。
purl_chunks <- function(input_file){
purled <- knitr::purl(input_file) # purl original file; save name to variable
lines <- readLines(purled) # read purled file into a character vector of lines
starts <- grep('^## ----.*-+', lines) # use grep to find header row indices
stops <- c(starts[-1] - 1L, length(lines)) # end row indices
# extract chunk names from headers
names <- sub('^## ----([^-]([^,=]*[^,=-])*)[,-][^=].*', '\1', lines[starts])
names <- ifelse(names == lines[starts], '', paste0('_', names)) # clean if no chunk name
# make nice file names with chunk number and name (if exists)
file_names <- paste0('chunk_', seq_along(starts), names, '.R')
for(chunk in seq_along(starts)){ # loop over header rows
# save the lines in the chunk to a file
writeLines(lines[starts[chunk]:stops[chunk]], con = file_names[chunk])
}
unlink(purled) # delete purled file of entire document
}
几个注意事项:
- 虽然正则表达式可以满足我的要求,但它可能会出错。测试:
- 没有区块名称
- 没有名称,只有区块设置
- 带连字符的名称
- 单字符名称
- 带空格的名称,包括之后(comma/brace之前)
- 由于
.Rnw
和 .Rmd
文件都 purl
相同,它适用于任何一个。
purl
的 documentation
参数使用默认设置 (1L
)。 0L
不会有块 headers,因此在这里毫无意义,但它会愚蠢地处理 2L
(这将包括文本块作为 roxygen
评论)。但是,如果您想要具有以下代码块的文本块,则可以为此重建它。
- 虽然
purl
的输出 header 行看起来与上面的示例不完全相同(它们以 ## ----
开头并用连字符填充),但它们 spin
适当地;结果服从块选项。
出于教学目的,我想 purl
我的 .Rnw
文件的块分成单独的文件。这个答案解释了如何去做:
How to purl each chunks in .Rmd file to multiple .R files using Knitr
但是该方法不保留块选项。由于我生成的块会生成图,因此保留 fig.width
和 fig.height
选项很重要。理想情况下,我想要一个看起来像这样的块:
<<plot, fig.width = 3, fig.height = 5, outwidth = '.75\textwidth'>>=
plot (1,1)
@
成为一个名为 plot.R
的文件,如下所示:
#+ fig.width = 3, fig.height = 5
plot (1,1)
也就是把块选项fig.width
和fig.height
变成spin()
可以识别的格式,就像purl()
一样,去掉不相关的块选项,或者为 spin()
到 Word 中创建问题,例如 out.width
。本着创建用户友好的代码文件的精神。
由于您引用的答案没有从 purl
的结果中复制 header 行,因此您丢失了除块名称之外的所有内容。虽然您可以调整它以粘贴到 header 中,但实际上构建一个函数来解析 purl
的输出并不难——比尝试解析 Rmd
或 [= 容易得多14=] 文档,无论如何,比弄清楚 knitr
是如何做到的更容易。
purl_chunks <- function(input_file){
purled <- knitr::purl(input_file) # purl original file; save name to variable
lines <- readLines(purled) # read purled file into a character vector of lines
starts <- grep('^## ----.*-+', lines) # use grep to find header row indices
stops <- c(starts[-1] - 1L, length(lines)) # end row indices
# extract chunk names from headers
names <- sub('^## ----([^-]([^,=]*[^,=-])*)[,-][^=].*', '\1', lines[starts])
names <- ifelse(names == lines[starts], '', paste0('_', names)) # clean if no chunk name
# make nice file names with chunk number and name (if exists)
file_names <- paste0('chunk_', seq_along(starts), names, '.R')
for(chunk in seq_along(starts)){ # loop over header rows
# save the lines in the chunk to a file
writeLines(lines[starts[chunk]:stops[chunk]], con = file_names[chunk])
}
unlink(purled) # delete purled file of entire document
}
几个注意事项:
- 虽然正则表达式可以满足我的要求,但它可能会出错。测试:
- 没有区块名称
- 没有名称,只有区块设置
- 带连字符的名称
- 单字符名称
- 带空格的名称,包括之后(comma/brace之前)
- 由于
.Rnw
和.Rmd
文件都purl
相同,它适用于任何一个。 purl
的documentation
参数使用默认设置 (1L
)。0L
不会有块 headers,因此在这里毫无意义,但它会愚蠢地处理2L
(这将包括文本块作为roxygen
评论)。但是,如果您想要具有以下代码块的文本块,则可以为此重建它。- 虽然
purl
的输出 header 行看起来与上面的示例不完全相同(它们以## ----
开头并用连字符填充),但它们spin
适当地;结果服从块选项。