Как условно исключить чанк после оценки его контента? - PullRequest
0 голосов
/ 15 февраля 2019

Я создаю параметризованный отчет в Rmarkdown, в то время как некоторые фрагменты не должны оцениваться (включаться в отчет) на основе характеристик содержимого внутри фрагмента.

В отчете вычисляются отдельные сводки по крупному опросу для ~ 120 объектов с различным количеством единиц в них.Кроме того, размер и объем единиц в значительной степени варьируются, поэтому мы исключаем анализ единиц, если число допустимых ответов на единицу меньше 10 (это уже перекодировано в NA в объекте dataframe).Поэтому мне нужно написать инструкцию, в которой подсчитывается количество NA в объекте на единицу, и если для каждой единицы есть только NA, я хотел бы включить include = FALSE в чанке.Это нужно повторить для ~ 50 кусков, поэтому я попытался использовать eval.after.

Комментарий Мартина Шмельцера заставил меня понять, что у меня есть 2 разные проблемы:

1) Мне нужно использоватьрегулярные выражения для определения имени объекта в самописанной функции в чанке.

2) Мне нужно настроить функцию для условной оценки eval.after в чанках.

Для задачи 1): R-Chunk, который необходимо проверить на наличие eval.after, выглядит следующим образом:

```{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( до , 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")

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

Вот способ вставить данные как параметр чанка, проверить их достоверность и вывести условное выражение kable для этого результата.Приятно то, что мы можем ссылаться на первый общий блок и вызывать его с другим фреймом данных.

С помощью knit_hooks$set мы создаем новый хук чанка с именем 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}
```
0 голосов
/ 15 февраля 2019

Вы можете изменить параметр чанка 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
```
...