Rmarkdown父文档向子文档外部脚本传参问题求解
问题描述
现有外部脚本test.R,以及子文档child1.Rmd、child2.Rmd和父文档parent.Rmd。期望通过父文档传递sex和generation两个参数给子文档,让加载的test.R根据不同参数生成对应结果。目前child2.Rmd能输出两种参数的预期结果,但child1.Rmd仅生成sex的结果,需解决child1.Rmd的适配问题。
相关代码文件
test.R
# ---- testA ---- data <- tribble( ~sex, ~generation, ~high, ~n, "M", 10, "high", 38, "M", 10, "low", 148, "F", 10, "high", 10, "F", 20, "low", 33) dat <- data |> group_by(!!sym(input_params$attribution)) |> # summarize(hoge) |> pivot_wider( names_from = input_params$attribution, values_from = "n") |> print() # ---- testB ---- result <- dat |> chisq.test() |> print()
原child1.Rmd
--- title: "child1" output: html_document --- ```{r, include=FALSE} library(tidyverse)
knitr::read_chunk('test.R') options(knitr.duplicate.label = "allow")
r input_params$attribution
### 原parent.Rmd ```rmarkdown --- title: "parent" output: html_document --- ```{r setup, include=FALSE} library(tidyverse)
# param_define params_df = tibble(attribution = c("sex", "generation")) res_list <- lapply(1:nrow(params_df), function(x) { input_params <- params_df[x,] knitr::knit_child('child1.Rmd', quiet = TRUE, envir = environment()) })
for (i in 1:nrow(params_df)) { cat(res_list[[i]]) cat("\n") }
## 原因分析 `child1.Rmd`仅生成`sex`结果的核心原因是**代码块缓存与环境共享问题**: - `knitr::read_chunk('test.R')`读取的代码块会被默认缓存,第一次编译`sex`参数后,`testA`代码块的执行逻辑被固定; - 父文档循环编译时,子文档共享了同一个环境,第二次传递`generation`参数时,缓存的`testA`代码不会重新读取,直接复用了第一次的参数上下文。 而`child2.Rmd`直接内嵌了`test.R`的代码,每次编译都会重新执行,不受缓存影响,因此能正确响应动态参数。 ## 解决方法 ### 调整child1.Rmd 修改代码块配置,强制禁用缓存并刷新代码绑定: ```rmarkdown --- title: "child1" output: html_document --- ```{r, include=FALSE} library(tidyverse)
# 清除testA代码块的缓存,确保每次重新读取 knitr::purge_cache("testA") knitr::read_chunk('test.R') options(knitr.duplicate.label = "allow")
r input_params$attribution
给testA代码块添加cache=FALSE,彻底禁用缓存
### 调整parent.Rmd 为每个子文档创建独立环境,避免参数污染: ```rmarkdown --- title: "parent" output: html_document --- ```{r setup, include=FALSE} library(tidyverse)
# param_define params_df = tibble(attribution = c("sex", "generation")) res_list <- lapply(1:nrow(params_df), function(x) { # 为每个子文档创建独立的执行环境 child_env <- new.env(parent = globalenv()) child_env$input_params <- params_df[x,] knitr::knit_child('child1.Rmd', quiet = TRUE, envir = child_env) })
for (i in 1:nrow(params_df)) { cat(res_list[[i]]) cat("\n") }
## 关键说明 - `knitr::purge_cache("testA")`:强制清除指定代码块的缓存,确保每次编译都读取最新的`test.R`内容; - 独立环境`child_env`:避免不同参数的编译过程共享变量上下文,防止参数值被覆盖; - `cache=FALSE`:给`testA`代码块明确禁用缓存,保证每次都重新执行代码逻辑。 内容的提问来源于stack exchange,提问作者せきぐち
相关产品推荐
相关产品推荐

