Модульная структура уценки R

По этому поводу уже есть несколько вопросов, но они либо неясны, либо предлагают решения, которые не работают, возможно, потому, что они устарели:

Модульная структура кода для больших проектов

R Markdown/Notebook хорош, но в том виде, в котором он представлен, обычно есть один файл, содержащий весь текст и все фрагменты кода. У меня часто бывают проекты, где такая единая файловая структура не является хорошей настройкой. Вместо этого я использую один мастер-файл .R, который загружает другие файлы .R по порядку. Я хотел бы воспроизвести эту структуру с помощью R Notebook, т.е. чтобы у меня был один файл .Rmd, из которого я вызываю код из нескольких файлов .R.

Преимущество такого способа работы с проектом заключается в том, что он обеспечивает нормальный рабочий процесс с RStudio с использованием файлов .R, а также аккуратный вывод из R Notebook/Markdown без дублирования кода.

Минимальный пример

Это упрощено, чтобы сделать пример как можно меньше. Два файла .R и один мастер-файл .Rmd.

start.R

# libs --------------------------------------------------------------------
library(pacman)
p_load(dplyr, ggplot2)
#normally load a lot of packages here

# data --------------------------------------------------------------------
d = iris
#use iris for example, but normally would load data from file

# data manipulation tasks -------------------------------------------------
#some code here to extract useful info from the data
setosa = dplyr::filter(d, Species == "setosa")

plot.R

#setosa only
ggplot(setosa, aes(Sepal.Length)) +
  geom_density()

#all together
ggplot(d, aes(Sepal.Length, color = Species)) +
  geom_density()

И затем файл блокнота:

notebook.Rmd:

---
title: "R Notebook"
output:
  html_document: default
  html_notebook: default
---

First we load some packages and data and do slight transformation:

```{r start}
#a command here to load the code from start.R and display it
```

```{r plot}
#a command here to load the code from plot.R and display it
```

Желаемый результат

Желаемый результат — это тот, который получается при ручном копировании кода из start.R и plot.R в фрагменты кода в notebook.Rmd. Это выглядит так (некоторые отсутствуют из-за нехватки места на экране):

введите описание изображения здесь

Вещи, которые я пробовал

source

Это загружает код, но не отображает его. Он просто отображает команду source:

введите описание изображения здесь

knitr::read_chunk

Эта команда упоминалась здесь, но на самом деле она делает то же самое, что и source, насколько я могу судить : он загружает код, но ничего не отображает.

введите описание изображения здесь

Как получить желаемый результат?


person CoderGuy123    schedule 10.11.2016    source источник


Ответы (3)


Решение состоит в том, чтобы использовать опцию code блока вязания. Согласно документам knitr:

код: (NULL; символ), если указан, он переопределит код в текущем фрагменте; это позволяет нам программно вставлять код в текущий фрагмент; например код опции блока = Capture.output(dump('fivenum', '')) будет использовать исходный код функции Fivenum для замены текущего блока

Однако пример не приводится. Похоже, нужно передать ему вектор символов, поэтому давайте попробуем readLines:

```{r start, code=readLines("start.R")}
```

```{r plot, code=readLines("start.R")}
```

Это дает желаемый результат и, таким образом, позволяет использовать модульную структуру проекта.

Подача файла напрямую не работает (например, code="start.R"), но было бы хорошим улучшением.

person CoderGuy123    schedule 10.11.2016
comment
Это здорово. Поскольку у меня есть структура папок, я объединил ее с библиотекой here, которая помогает с папками проектов в RStudio. - person No More Hacks; 17.04.2018

Для взаимодействия с R Notebooks вы можете использовать метод read_chunk вязания, как описано выше. В записной книжке вы должны вызвать read_chunk в блоке установки; поскольку вы можете запускать фрагменты блокнота в любом порядке, это гарантирует, что внешний код всегда будет доступен.

Вот минимальный пример использования read_chunk для переноса кода из внешнего сценария R в записную книжку:

пример.Rmd

```{r setup}
knitr::read_chunk("example.R")
```

```{r chunk}
```

пример.R

## ---- chunk
1 + 1

Когда вы выполняете пустой фрагмент в записной книжке, код из внешнего файла будет вставлен, а результаты будут отображаться в строке, как если бы фрагмент содержал этот код.

Вывод блокнота

person Jonathan    schedule 21.03.2017

Согласно моему комментарию выше, я использую библиотеку здесь для работы с проектами в папках:

 ```{ r setup, echo=FALSE, message=FALSE, warning=FALSE, results='asis'}

library(here) 

insert <- function(filename){
  readLines(here::here("massive_report_folder", filename))
}
```

и тогда каждый кусок выглядит как

```{ r setup, echo=FALSE, message=FALSE, warning=FALSE, 
        results='asis', code=insert("extra_file.R")}
```
person No More Hacks    schedule 17.04.2018