我正在Rmarkdown中创建参数化报告,而不应根据块中内容的特征评估某些块(包含在报告中)。
该报告计算了大约120个设施的大型调查的个别摘要,其中包含不同数量的单位。另外,单位大小和数量在很大程度上是可变的,因此如果每单位的有效答案数小于10(我们已经在dataframe-object中将其重新编码为NA),我们就会排除单位分析。因此,我需要编写一个语句,其中一个对象中NA的数量按单位计算,如果每个单元只有NA,我想在块上做include = FALSE。这需要重复约50个块,因此我尝试使用eval.after。
Martin Schmelzer的评论让我意识到我有两个不同的问题:
1)我需要使用正则表达式来检测块中自编写函数中对象的名称。
2)我需要设置一个函数来有条件地评估eval.after在块中。
对于问题1):需要检查eval.after的R-Chunk如下所示:
```{r leadership unit, eval=exclude_ifnot_unitC }
kable.unit.tblc(unitblc_leadership, caption = "Führung")
```
kable.unit.tblc(df, caption)
是一个自编写的函数,它实现kableExtra()函数来设置表的样式,第一个输入是一个数据帧(事先在R文件中创建)。我现在应该使用正则表达式从块中提取数据帧的名称,这意味着来自kable.unit.tblc(
to , caption
的所有内容。
到目前为止,我尝试使用正则表达式的第一步,但是我无法在这两个表达式之间“获取”对象:
x <- 'kable.unit.tblc(unitblc_leadership, caption = "Führung")'
stringr::str_extract(x, "^kable.unit.tblc\\(")
stringr::str_extract(x, ", caption")
在这种情况下,提取的对象的期望结果将是unitblc_leadership
并存储在变量中,例如test_object
。
关于第二个问题:我应该为那些块设置eval.after = 'include_if_valid'
,测试它的功能是:
include_if_valid <- function() {
## search the chunk with regular expression for detecting the
# test object (Problem 1)
# count the number of NAs in all numeric variables of the
# test_object and if all cells are NA's give FALSE, if any
# cell has a value give TRUE
test_object %>%
select_if(is.numeric) %>%
summarise_all(.funs = list(~n.valid)) %>%
gather(key = "Unit", value = "nvalid") %>%
count(nvalid > 0) %>% pull(`nvalid > 0`)
正如你所看到的,我需要之前应该使用该函数导出的test_object
- 但我不确定我的意图是否可能。
然后块应该看起来像这样:
```{r leadership unit, eval.after=include_if_valid }
kable.unit.tblc(unitblc_leadership, caption = "Führung")
```
编辑:我觉得太复杂了 - 马丁的这个解决方案工作得很好:
include_if_valid <- function(df) {
if (df %>%
select_if(is.numeric) %>%
summarise_all(.funs = list(~n.valid)) %>%
gather(key = "Unit", value = "nvalid") %>%
pull() %>% sum() > 0) {TRUE} else {FALSE}
}
并在块内:
{r leadership unit, eval=include_if_valid(unitblc_leadership) }
kable.unit.tblc(unitblc_leadership, caption = "Führung")
您可以将块选项results
更改为"hide"
,但这必须在您开始评估块之前发生(因为eval.after
在其适用的选项中受限)。所以为了获得你想要的东西,你需要两个块:
你的例子不可复制,所以这里是一个简单的例子。假设我只想显示x
,如果它的值大于10:
```{r include=FALSE}
# compute x as a random value between 9 and 11, but don't display anything
x <- runif(1, 9, 11)
```
```{r include = x > 10}
# display x conditional on its value being > 10
x
```
这是一种将数据作为块选项注入,检查其有效性并以该结果打印kable条件的方法。好的是我们可以引用第一个通用块并使用不同的数据帧调用它。
通过knit_hooks$set
,我们创建了一个名为chunk hook的新df
。 if(before)
中的所有内容都将在评估块本身之前进行评估。参数options
包含为当前块设置的所有块选项,envir
是块环境。
---
title: "Conditional Evaluation"
output: html_document
---
```{r setup, include = F}
library(dplyr)
library(knitr)
A <- data.frame(A = LETTERS[1:4])
B <- data.frame(B = rep(NA, 4))
C <- data.frame(C = letters[1:4])
include_if_valid <- function(df) {
return(all(!is.na(df)))
}
knit_hooks$set(df = function(before, options, envir) {
if (before) {
assign("valid", include_if_valid(options$df), envir = envir)
}
})
```
```{r generic, df = A, echo = F}
if(valid) kable(opts_current$get("df"))
```
```{r ref.label="generic", df = B, echo = F}
```
```{r ref.label="generic", df = C, echo = F}
```