`source( 'myfile.r')`のようなRマークダウンファイルを調達する方法は?


89

メインのRMarkdownファイルまたはknitrLaTeXファイルがありsource、他のRファイル(データ処理など)があります。ただし、場合によっては、これらのソースファイルを独自の再現可能なドキュメントにすることが有益であると考えていました(たとえば、データ処理のコマンドを含むだけでなく、データ処理の決定を説明する再現可能なドキュメントを生成するRマークダウンファイル)。

したがって、source('myfile.rmd')メインのRMarkdownファイルのようなコマンドが必要です。これは、のRコードチャンク内のすべてのRコードを抽出してソースしますmyfile.rmd。もちろん、これはエラーを引き起こします。

次のコマンドが機能します。

```{r message=FALSE, results='hide'}
knit('myfile.rmd', tangle=TRUE)
source('myfile.R')
```

ここで、results='hide'出力が所望された場合は省略することができます。つまり、knitrはRコードをからmyfile.rmdに出力しmyfile.Rます。

ただし、完璧ではないようです。

  • その結果、余分なファイルが作成されます
  • 表示を制御する必要がある場合は、独自のコードチャンクに表示する必要があります。
  • シンプルほどエレガントではありませんsource(...)

したがって、私の質問: RマークダウンファイルのRコードを調達するよりエレガントな方法はありますか?


私は実際にあなたの質問を理解するのに本当に苦労しています(私はそれを数回読みました)。他のRスクリプトを簡単にRmdファイルに取り込むことができます。しかし、他のmarkdownファイルを編んでいるファイルにソースしたいですか?
マイアサウラ2012年

4
Rマークダウンファイル(つまり、*。rmd)のRコードチャンク内のRコードを調達したいですか?質問を少し編集して、わかりやすくしました。
ジェロミーアングリム2012年

includeラテックスのラインに沿った何か。マークダウンが他のマークダウンドキュメントの包含をサポートしている場合、そのような関数を作成するのは比較的簡単です。
Paul Hiemstra 2012年

@PaulHiemstraテキストとRコードチャンクを調達する機能も役立つと思います。私は特に、RMarkdownドキュメントのコードだけを調達することを考えています。
ジェロミーアングリム2012年

回答:


35

あなたはワンライナーを探しているようです。これを入れてみ.Rprofileませんか?

ksource <- function(x, ...) {
  library(knitr)
  source(purl(x, output = tempfile()), ...)
}

ただし、source()Rmdファイル自体のコードが必要な理由がわかりません。私は意味knit()、この文書ですべてのコードを実行され、あなたがコードを抽出し、チャンクでそれを実行する場合、すべてのコードが実行される二回したときknit()、この文書(自分自身の内側に自分自身を実行します)。2つのタスクは別々にする必要があります。

本当にすべてのコードを実行したい場合、RStudioはこれをかなり簡単にしましたCtrl + Shift + R。それは基本的に呼び出すpurl()と、source()シーンの背後にあります。


8
こんにちは@Yihui分析が小さなスクリプトで構成されている場合があるので便利だと思いますが、レポートではパイプライン全体のコードが必要です。
ルカセロン2014

9
したがって、ここでの使用例は、すべてのコードを記述し、それを詳細に文書化して説明する必要があるが、コードは他のスクリプトによって実行されるというものです。
Brash Equilibrium

4
@BrashEquilibriumコードの使用source()またはknitr::knit()実行の問題です。私は人々が後者にあまり精通していないことを知っていますpurl()が、信頼できません。警告されました:github.com/yihui/knitr/pull/812#issuecomment-53088636
Xie

5
@Yihuiあなたの見解では、「source(purl(x、...))」の代替案は何でしょうか?重複するチャンクラベルに関するエラーが発生することなく、1つのソースで複数の* .Rmd-Filesを取得するにはどうすればよいですか?ソースになるドキュメントに戻って編みたくはありません。私は多くのファイルに* .Rmdを使用していますが、エクスポートして他の人と話し合う必要がある可能性があるため、分析のすべてのステップで複数のRmdファイルを入手できると便利です。
stats-hb 2017年

knitrは、.rmdファイルをレンダリングするときに、「エラー:必要なパッケージがありません」というエラーを発行します。不足しているパッケージの名前を含む実際のエラーメッセージを見つけるには、.rmdファイルのコードを実行する必要があります。svmでは1つのケースがcaret必要ですkernlab
CW

19

共通コードを個別のRファイルに分解し、そのRファイルを必要な各Rmdファイルにソースします。

たとえば、インフルエンザの発生と銃とバターの分析という2つのレポートを作成する必要があるとします。当然、2つのRmdドキュメントを作成して、それで完了します。

ここで、上司がやって来て、インフルエンザの発生とバターの価格の違いを確認したいとします(9mm弾薬を制御)。

  • レポートを分析するためにコードをコピーして新しいレポートに貼り付けることは、コードの再利用などにはお勧めできません。
  • 見栄えがいいです。

私の解決策は、プロジェクトを次のファイルに分解することでした。

  • Flu.Rmd
    • flu_data_import.R
  • Guns_N_Butter.Rmd
    • guns_data_import.R
    • butter_data_import.R

各Rmdファイル内には次のようなものがあります。

```{r include=FALSE}
source('flu_data_import.R')
```

ここでの問題は、再現性が失われることです。これに対する私の解決策は、各Rmdファイルに含める共通の子ドキュメントを作成することです。したがって、作成するすべてのRmdファイルの最後に、次を追加します。

```{r autodoc, child='autodoc.Rmd', eval=TRUE}
``` 

そしてもちろん、autodoc.Rmd:

Source Data & Code
----------------------------
<div id="accordion-start"></div>

```{r sourcedata, echo=FALSE, results='asis', warnings=FALSE}

if(!exists(autodoc.skip.df)) {
  autodoc.skip.df <- list()
}

#Generate the following table:
for (i in ls(.GlobalEnv)) {
  if(!i %in% autodoc.skip.df) {
    itm <- tryCatch(get(i), error=function(e) NA )
    if(typeof(itm)=="list") {
      if(is.data.frame(itm)) {
        cat(sprintf("### %s\n", i))
        print(xtable(itm), type="html", include.rownames=FALSE, html.table.attributes=sprintf("class='exportable' id='%s'", i))
      }
    }
  }
}
```
### Source Code
```{r allsource, echo=FALSE, results='asis', warning=FALSE, cache=FALSE}
fns <- unique(c(compact(llply(.data=llply(.data=ls(all.names=TRUE), .fun=function(x) {a<-get(x); c(normalizePath(getSrcDirectory(a)),getSrcFilename(a))}), .fun=function(x) { if(length(x)>0) { x } } )), llply(names(sourced), function(x) c(normalizePath(dirname(x)), basename(x)))))

for (itm in fns) {
  cat(sprintf("#### %s\n", itm[2]))
  cat("\n```{r eval=FALSE}\n")
  cat(paste(tryCatch(readLines(file.path(itm[1], itm[2])), error=function(e) sprintf("Could not read source file named %s", file.path(itm[1], itm[2]))), sep="\n", collapse="\n"))
  cat("\n```\n")
}
```
<div id="accordion-stop"></div>
<script type="text/javascript">
```{r jqueryinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://code.jquery.com/jquery-1.9.1.min.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r tablesorterinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://tablesorter.com/__jquery.tablesorter.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r jqueryuiinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://code.jquery.com/ui/1.10.2/jquery-ui.min.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r table2csvinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(file.path(jspath, "table2csv.js")), sep="\n")
```
</script>
<script type="text/javascript">
  $(document).ready(function() {
  $('tr').has('th').wrap('<thead></thead>');
  $('table').each(function() { $('thead', this).prependTo(this); } );
  $('table').addClass('tablesorter');$('table').tablesorter();});
  //need to put this before the accordion stuff because the panels being hidden makes table2csv return null data
  $('table.exportable').each(function() {$(this).after('<a download="' + $(this).attr('id') + '.csv" href="data:application/csv;charset=utf-8,'+encodeURIComponent($(this).table2CSV({delivery:'value'}))+'">Download '+$(this).attr('id')+'</a>')});
  $('#accordion-start').nextUntil('#accordion-stop').wrapAll("<div id='accordion'></div>");
  $('#accordion > h3').each(function() { $(this).nextUntil('h3').wrapAll("<div>"); });
  $( '#accordion' ).accordion({ heightStyle: "content", collapsible: true, active: false });
</script>

注意、これはRmd-> htmlワークフロー用に設計されています。あなたがラテックスまたは他のものと一緒に行くならば、これは醜い混乱になるでしょう。このRmdドキュメントは、グローバル環境ですべてのsource()されたファイルを検索し、ドキュメントの最後にそれらのソースを含めます。jquery ui、tablesorterが含まれ、アコーディオンスタイルを使用してソースファイルを表示/非表示にするようにドキュメントを設定します。これは進行中の作業ですが、ご自身の用途に自由に適合させてください。

ワンライナーではありません、私は知っています。それが少なくともあなたにいくつかのアイデアを与えることを願っています:)


4

おそらく、人は違う考えを始めるべきです。私の問題は次のとおりです。通常は.Rファイルの.Rmdチャンクにあるすべてのコードを記述します。そして、あなたが編み物に使用するRmdドキュメント、つまりhtmlの場合、あなたは残っているだけです

```{R Chunkname, Chunkoptions}  
source(file.R)  
```

このようにすると、おそらく多数の.Rファイルが作成され、ctrl + alt + n(または+ cですが、通常は機能しません)を使用してすべてのコードを「チャンクごとに」処理するという利点が失われます。しかし、Gandrud氏の再現性のある研究に関する本を読んだところ、彼は間違いなくHTMLファイルの作成にのみknitrファイルと.Rmdファイルを使用していることに気付きました。メイン分析自体は.Rファイルです。内部で分析全体を実行し始めると、.Rmdドキュメントが急速に大きくなりすぎると思います。


3

あなたがコードの直後にいるなら、私はこれらの線に沿った何かがうまくいくはずだと思います:

  1. マークダウン/ Rファイルを readLines
  2. たとえばgrepで始まる行を検索して、コードチャンクを検索するために使用します<<<
  3. 元の行を含むオブジェクトのサブセットを取得して、コードのみを取得します
  4. を使用してこれを一時ファイルにダンプします writeLines
  5. このファイルをRセッションにソースします

これを関数でラップすると、必要なものが得られるはずです。


1
ありがとう、私はそれがうまくいくと思います。ただし、最初の4つのポイントknit('myfile.rmd', tangle=TRUE)は、StangleがSweaveに対して信頼できる方法ですでに行っていることと、knitrで行っていることのように聞こえます。もつれとソースの両方があり、理想的にはファイルを作成しない1つのライナーを探していると思います。
ジェロミーアングリム2012年

関数でラップすると、ワンライナーになります;)。あなたができることはtextConnection、ファイルを模倣するために使用し、そこからソースを作成することです。これにより、ファイルが作成されなくなります。
Paul Hiemstra 2012年

はい。textConnection見る場所かもしれません。
ジェロミーアングリム2012年

2

次のハックは私にとってはうまくいきました:

library(readr)
library(stringr)
source_rmd <- function(file_path) {
  stopifnot(is.character(file_path) && length(file_path) == 1)
  .tmpfile <- tempfile(fileext = ".R")
  .con <- file(.tmpfile) 
  on.exit(close(.con))
  full_rmd <- read_file(file_path)
  codes <- str_match_all(string = full_rmd, pattern = "```(?s)\\{r[^{}]*\\}\\s*\\n(.*?)```")
  stopifnot(length(codes) == 1 && ncol(codes[[1]]) == 2)
  codes <- paste(codes[[1]][, 2], collapse = "\n")
  writeLines(codes, .con)
  flush(.con)
  cat(sprintf("R code extracted to tempfile: %s\nSourcing tempfile...", .tmpfile))
  source(.tmpfile)
}

2

次のカスタム関数を使用します

source_rmd <- function(rmd_file){
  knitr::knit(rmd_file, output = tempfile())
}

source_rmd("munge_script.Rmd")


1

メインの分析コードと計算コードを.Rファイルに保持し、必要に応じて.Rmdファイルにチャンクをインポートすることをお勧めします。ここでプロセスを説明しました


1

sys.source( "./ your_script_file_name.R"、envir = knitr :: knit_global())

your_script_file_name.Rに含まれている関数を呼び出す前に、このコマンドを入力してください。

すでにプロジェクトを作成している場合は、ファイルへの方向を示すためにyour_script_file_name.Rの前に「./」を追加します。

詳細については、次のリンクを参照してください:https//bookdown.org/yihui/rmarkdown-cookbook/source-script.html


0

これは私のために働いた

source("myfile.r", echo = TRUE, keep.source = TRUE)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.