quarto-webrはいいぞ

Quarto
webR
Author

statditto

Published

May 12, 2024

はじめに

先日開催されたTokyo.R#112ではじめてのLTをしました。発表資料に、quarto-webrをしれっと利用してみたところ、使用感がかなり良かったです。チョットダケ需要がありそうなので記事にしておくことにします。

公式ドキュメント以上のことは特に記載していないので、発展的な内容に興味がある方は公式ドキュメントを参照してください。

quarto-webrとは

quarto-webrはその名の通りQuartoでwebRを利用できるようにするQuartoの拡張機能です。そもそもwebRってなんだっけ?という方は、先にえいつぴさんのブログ記事を読むとよさそうです。現時点でおそらく唯一の日本語文献です。

ブラウザで動くR、WebRが熱い!

webRについて適当な説明をすると、「ブラウザでRを使えてうれしい!」みたいな感じです。 ですが、webRを直接利用するのは結構大変です。たとえば、次のようなインタラクティブなコードエディターを描写するためには、そこそこたくさんのJavaScriptを書く必要があります1

fit <- lm(mpg ~ am, data=mtcars) summary(fit)
コード(非同期処理なにも分からない)
<button class="btn btn-success btn-sm" disabled type="button" id="runButton">Loading webR...</button>
<div id="editor">fit <- lm(mpg ~ am, data=mtcars)
summary(fit)</div>
<pre><code id="out"></code></pre>
<canvas
  id="canvas"
  width="1008"
  height="1008"
  style="display: none; margin: auto; width: 700px;"
></canvas>
<script type="module">
  var editor = ace.edit("editor");
  editor.setOptions({ fontSize: "11pt", maxLines: Infinity });
  editor.session.setMode("ace/mode/r");


  import { WebR } from 'https://webr.r-wasm.org/v0.3.3/webr.mjs';
  const webR = new WebR();
  await webR.init();
  await webR.evalRVoid('options(device=webr::canvas)');
  const shelter = await new webR.Shelter();


  // Handle webR output messages in an async loop
  (async ()=>{
    for (;;) {
      const output = await webR.read();
      switch (output.type) {
        case 'canvas':
          let canvas = document.getElementById('canvas');
          if (output.data.event === 'canvasNewPage') {
            canvas.style.display = 'block';
            canvas.getContext('2d').clearRect(0, 0, 1008, 1008);
          }
          if (output.data.event === 'canvasImage') {
            canvas.getContext('2d').drawImage(output.data.image, 0, 0);
          }
          break;
        default:
          break;
      }
    }
  })();


  async function runR() {
    document.getElementById('canvas').style.display = 'none';
    let code = editor.getValue();
    const result = await shelter.captureR(code, {
      withAutoprint: true,
      captureStreams: true,
      captureConditions: false
    });
    try {
      const out = result.output.filter(
        evt => evt.type == 'stdout' || evt.type == 'stderr'
      ).map((evt) => evt.data);
      document.getElementById('out').innerText = out.join('\n');
    } finally {
      shelter.purge();
    }
  }
  document.getElementById('runButton').onclick = runR;
  document.getElementById('runButton').innerText = 'Run code';
  document.getElementById('runButton').disabled = false;


</script>

quarto-webrは、この苦しさをいい感じにラッピングすることでeasyにwebRを利用可能としてくれます。とてもうれしいです。

インストール

まずは拡張機能を利用したいプロジェクトフォルダの配下で以下のコマンドを実行して、拡張機能をインストールします。

quarto add coatless/quarto-webr

Quarto の拡張機能はRのパッケージとは異なり、globalな場所にインストールされるわけでは無いので注意してください。_extensions配下に拡張機能が追加されたことを確認したら次に進みましょう。

利用法

適当な.qmdファイルを作成しましょう。作成したら次の手順でquarto-webrを利用出来ます。

  1. ドキュメントのyamlヘッダーにwebrを追加する
filters:
  - webr
  1. コードブロックで{webr-r}を利用する
---
title: ねこになりたいね
format: html
engine: knitr
filters:
  - webr
---

`quarto-webr`のおかげで、成績も上がったしねこにもなれました!

```{webr-r}
fit = lm(mpg ~ am, data = mtcars)
summary(fit)
```
  1. レンダリングする

いい感じにインタラクティブなコードエディターが現れます。生のwebRを利用するよりも圧倒的に簡単ですね。しかもHTMLRevealJSウェブサイトブログ書籍の形式に対応しているのでいろいろなシーンで使えます。

Tipsとか

個人的に知っておくと便利そうだと思ったこと、引っかかったことをいくつか記載しておきます。

パッケージのinstallについて

webRではwebr::install()関数で対話的にパッケージをインストールできます。

webr::install("ggplot2")

講義資料やハンズオンでquarto-webrを利用する場合では、ドキュメント内で利用するパッケージはあらかじめインストールしておきたいのではないかと思います。ドキュメントを開いたときにパッケージのインストールを開始したい場合は次のようにyamlヘッダーを修正しましょう。

---
webr:
  packages: ['dplyr', 'tidylog']
---

パッケージは記述した順にインストールが行われるため、競合するパッケージをインストールする場合は気を付けましょう(一敗)。

データの読み込み

次の二つの方法がサポートされているようです。

  1. パッケージ内のデータを読み込む
  2. webから読み込む

指定のurlか次のように読み込むことが出来ます。

url <- "https://example.com/data.csv"
download.file(url, "data.csv")
data <- read.csv("data.csv")

ドキュメントとセルのオプション

生のquartoで利用できるオプションがquarto-webrでは利用できないことがあります(一敗)。指定したのに適用されていないな~と思った場合は、ドキュメントを確認しましょう。

バージョンの互換性

古いバージョンのQuartoで作業していたら拡張機能をインストールしてもコードエディターがレンダリングされず、長い間苦しみました(一敗)2quarto-webrは公式の拡張機能ではないこともあり、特定のバージョンでは動作しない、予期せぬバグが発生する事がありそうです。僕のケースではQuartoを最新版にするだけで期待通り動くようになりましたが、逆に最新版のQuartoにquarto-webrのアップデートが追い付いていないケースも見受けられます。公式レポジトリのissueなどをチェックしてあげるといいと思います。

終わりに

R最高!