如何在评估内容后有条件地排除大块?

问题描述 投票:1回答:2

我正在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")
r r-markdown knitr
2个回答
2
投票

您可以将块选项results更改为"hide",但这必须在您开始评估块之前发生(因为eval.after在其适用的选项中受限)。所以为了获得你想要的东西,你需要两个块:

  1. 计算足以确定是否应计算和显示块。如果不需要显示,请隐藏此项。
  2. 在下一个块中,如果要显示它们,则重复计算,并显示结果,所有条件都取决于先前计算的结果。

你的例子不可复制,所以这里是一个简单的例子。假设我只想显示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
```

1
投票

这是一种将数据作为块选项注入,检查其有效性并以该结果打印kable条件的方法。好的是我们可以引用第一个通用块并使用不同的数据帧调用它。

通过knit_hooks$set,我们创建了一个名为chunk hook的新dfif(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}
```
© www.soinside.com 2019 - 2024. All rights reserved.