R knitr: czy można programowo modyfikować etykiety?

Próbuję użyć knitr do wygenerowania raportu, który wykonuje ten sam zestaw analiz na różnych podzbiorach zbioru danych. Projekt zawiera dwa pliki Rmd: pierwszy plik jest dokumentem głównym, który ustawia obszar roboczy i dokument, drugi plik zawiera tylko fragmenty, które wykonują analizy i generuje powiązane dane.

To, co chciałbym zrobić, to zrobić plik główny, który następnie wywoła drugi plik dla każdego podzbioru danych i zamieści wyniki w jednym dokument. Poniżej znajduje się prosty przykład.

Główny dokument:

# My report

```{r}
library(iterators)
data(mtcars)
```

```{r create-iterator}
cyl.i <- iter(unique(mtcars$cyl))
```

## Generate report for each level of cylinder variable
```{r cyl4-report, child='analysis-template.Rmd'}
```

```{r cyl6-report, child='analysis-template.Rmd'}
```

```{r cyl8-report, child='analysis-template.Rmd'}
```

Analiza-szablon.Rmd:

```{r, results='asis'}
cur.cyl <- nextElem(cyl.i)
cat("###", cur.cyl)
```

```{r mpg-histogram}
hist(mtcars$mpg[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders"))
```

```{r weight-histogam}
hist(mtcars$wt[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders"))
```

Problem polega na tym, że dzianina nie pozwala na unikalne etykiety, więc dzianie zawodzi, gdy analysis-template.Rmd jest wywoływany po raz drugi. Tego problemu można uniknąć, pozostawiając kawałki bez nazwy, ponieważ unikalne etykiety byłyby wtedy automatycznie generowane. Nie jest to jednak idealne rozwiązanie, ponieważ chciałbym użyć etykiet fragmentów do tworzenia informacyjnych nazw plików dla eksportowanych plików działki.


Potencjalnym rozwiązaniem byłoby użycie prostej funkcji, która dołącza aktualny cylinder do etykiety fragmentu:

```r{paste('cur-label', cyl, sep = "-")}
```

Ale nie wydaje się, aby knitr oceniał wyrażenie w pozycji etykiety kawałka.


Próbowałem również użyć niestandardowegochunk hook , który zmodyfikował Etykietę bieżącego kawałka:

knit_hooks$set(cyl.suffix = function(before, options, envir) {
    if (before) options$label <- "new-label"
})

Ale zmiana etykiety chunk nie wpłynęła na nazwy plików dla generowanych Wykresów, więc nie sądziłem, że knitr wykorzystuje nowy Etykieta.


Jakieś pomysły, jak zmienić etykiety fragmentów, aby ten sam dokument potomny mógł być wywoływany wielokrotnie? A może alternatywna strategia, aby to osiągnąć?

 37
Author: aaronwolen, 2012-08-23

2 answers

Dla każdego, kto natknie się na ten post, chciałem zwrócić uwagę, że @Yihui dostarczył formalne rozwiązanie na to pytanie w knitr 1.0 wraz z wprowadzeniem funkcji knit_expand(). To działa świetnie i naprawdę uprościło mój przepływ pracy.

Na przykład poniższy skrypt szablonu będzie przetwarzany dla każdego poziomu mtcars$cyl, za każdym razem zastępując wszystkie instancje {{ncyl}} (w szablonie) aktualną wartością:

# My report

```{r}
data(mtcars)
cyl.levels <- unique(mtcars$cyl)
```

## Generate report for each level of cylinder variable
```{r, include=FALSE}
src <- lapply(cyl.levels, function(ncyl) knit_expand(file = "template.Rmd"))
```

`r knit(text = unlist(src))`

Szablon:

```{r, results='asis'}
cat("### {{ncyl}} cylinders")
```

```{r mpg-histogram-{{ncyl}}cyl}
hist(mtcars$mpg[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```

```{r weight-histogam-{{ncyl}}cyl}
hist(mtcars$wt[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```
 35
Author: aaronwolen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-15 15:03:17

Jeśli zrobisz wszystkie kawałki w swoim ** bezimiennym, tzn. ```{r} to działa. To oczywiście nie jest zbyt eleganckie, ale są dwa problemy uniemożliwiające zmianę etykiety bieżącego fragmentu:

  1. plik jest przetwarzany przed wykonaniem bloków kodu. Parser już wykrywa zduplikowane etykiety, zanim jakikolwiek kod zostanie wykonany lub zostaną wywołane niestandardowe Hooki.
  2. the chunk options (inc. etykieta) są przetwarzane przed wywołaniem Hooka (logiczne: jest to opcja, która uruchamia hak), więc hak nie może już zmienić etykiety.

Fakt, że nienazwane bloki działają, polega na tym, że wewnętrznie otrzymują Etykietę unnamed-chunk-+numer kawałka.

Bloki nie mogą mieć zduplikowanych nazw, ponieważ wewnętrznie knitr odwołuje się do nich za pomocą etykiety. Poprawką może być dodanie numeru kawałka do wszystkich kawałków o zduplikowanych nazwach. Albo odwoływać się do nich za pomocą numeru kawałka zamiast etykiety, ale wydaje mi się to znacznie większą zmianą.

 15
Author: ROLO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-23 18:27:41