2014-10-21 2 views
5

Когда я обрабатываю файлы разметки Rmd, которые использовали кешированные фрагменты в RStudio с помощью кнопки Knit HTML, я обнаружил, что порядок загрузки пакетов не запоминается из фрагмента кусок. Это вызывает проблемы, когда мне нужно загружать пакеты в определенном порядке, чтобы избежать конфликтов пространства имен.knitr, вызванный из RStudio, не сохраняет порядок загрузки пакетов

Для воспроизводимого примера (для которого необходимо установить пакеты plyr, dplyr и pryr, см. Ниже), я начинаю с создания документа Ritd knitr, который загружает plyr, а затем dplyr (которые оба экспортируют функцию summarise) затем использует pryr, чтобы определить, какая функция суммирования найдена. Я вязать это с помощью кнопки RStudio в «Knit HTML»:

```{r} 
library(knitr) 
opts_chunk$set(cache = TRUE, message = FALSE) 
``` 

```{r test1} 
library(plyr) 
library(dplyr) 
``` 

```{r test2, dependson = "test1"} 
attr(pryr::where("summarise"), "name") 
``` 

В соответствии с рекомендациями here, я загружаю plyr перед тем dplyr так функции, dplyr должны прийти первой в пути поиска. Как и следовало ожидать, выходной файл мД показывает, что функция summarise происходит от dplyr:

attr(pryr::where("summarise"), "name") 
## [1] "package:dplyr" 

Однако, если сделать некоторые небольшие изменения в test2 порции:

```{r test2, dependson = "test1"} 
attr(pryr::where("summarise"), "name") # this is a change 
``` 

, что заставляет его быть перекомпилированы, теперь загружает пакеты в неправильном порядке, и summarise находится в plyr:

attr(pryr::where("summarise"), "name") # this is a change 
## [1] "package:plyr" 

Обратите внимание, что эта проблема не возникает, если вы запускаете knit из командной строки R, но это связано только с тем, что она сохраняет загруженные в среду пакеты plyr и dplyr (если я перезапущу R, возникает та же проблема).

Мне известно, что я могу ссылаться на функции как dplyr::summarise во избежание избыточности, но это довольно громоздко. Не загружать plyr вообще не вариант, так как несколько пакетов непреднамеренно добавляют его в пространство имен. Как я могу обеспечить загрузку пакетов в нужном порядке?

Я использую последнюю версию RStudio (0.98.1079), и мой sessionInfo ниже:

## R version 3.1.1 (2014-07-10) 
## Platform: x86_64-apple-darwin13.1.0 (64-bit) 
## 
## locale: 
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 
## 
## attached base packages: 
## [1] stats  graphics grDevices utils  datasets methods base  
## 
## other attached packages: 
## [1] plyr_1.8.1 dplyr_0.3.0.2 knitr_1.7  
## 
## loaded via a namespace (and not attached): 
## [1] assertthat_0.1 codetools_0.2-8 DBI_0.3.0  digest_0.6.4  
## [5] evaluate_0.5.5 formatR_1.0  htmltools_0.2.4 magrittr_1.0.0 
## [9] parallel_3.1.1 pryr_0.1.0.9000 Rcpp_0.11.2  rmarkdown_0.3.10 
## [13] rstudioapi_0.1 stringr_0.6.2 tools_3.1.1 

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

```{r} 
install.packages(c("devtools", "plyr", "dplyr")) 
devtools::install_github("hadley/pryr") 
``` 
+1

Это также происходит, если вы используете 'cache = FALSE'? – Andrie

+0

@Andrie: Нет (и я бы этого не ожидал), хотя для моих целей необходимо кэширование. –

ответ

5

My pull request to knitr адресует эту проблему, сохраняя порядок поиска в файле __packages. Соответствующий код:

x = rev(.packages()) 
if (file.exists(path)) 
    x = setdiff(c(readLines(path), x), .base.pkgs) 
writeLines(x, path) 

@Yihui слил запрос как из this commit, и это, вероятно, будет доступен в knitr v1.8 в CRAN (или непосредственно из GitHub или RForge).

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

3

Опубликовать это как ответ, поскольку он кажется более существенным, чем комментарий.

Т.Л., др: попробуйте удалить cache/__packages вручную между запусками (и добавление cache=FALSE в свой пакет заряжания кусок/обходясь без кэширования пакетов) и посмотреть, если это решает проблему ... или даже добавить

if (file.exists("cache/__packages")) unlink("cache/__packages") 

(я не тестировал это на примере.)

у меня было много неприятностей с кэширования пакетов, особенно в рабочие каталоги, где я бегу много примеров с не-обязательно совместимые комплекты пакетов. Я часто просто удаляю cache/__packages вручную.Я предполагаю, что дизайн может быть улучшен (но я не потрудился строить примеры/думать о том, как дизайн будет улучшен).

+2

Загрузка пакетов имеет побочные эффекты, а побочные эффекты, как правило, опасны для кеширования. Простое решение, как описано в http://yihui.name/knitr/demo/cache/, не предназначено для кэширования фрагментов кода, которые имеют побочные эффекты. Если кто-то знает, как улучшить текущий дизайн или хочет работать над ним, не стесняйтесь отправлять запросы на тяну. –

+2

@Yihui: Спасибо. Я отправил [такой запрос] (https://github.com/yihui/knitr/pull/867). Я подтвердил, что это решает проблему на моем воспроизводимом примере, и если нет особых причин для хранения пакетов в алфавитном порядке, я не думаю, что это может вызвать проблемы. –

+0

@DavidRobinson Очень ценится! Я посмотрю позже. –

Смежные вопросы