reactRパッケージでRからReactを実行する

このエントリは R Advent Calendar 2017 20日目の記事です。

こんにちは。 最近Shinyでちょっと複雑なことをやりたくてJavaScriptを書いていたのですが、 どうせなら最近よく書いている React を使いたいなと思っていたところ、 reactR というドンピシャなパッケージを見つけたので紹介します。

github.com

なぜReactなのか

ReactFacebook製のUIを構築するためのJavaScriptライブラリです。 シングルページアプリケーションを作るときなどによく採用され、近年人気を博しています。 詳しい解説はネット上にいくらでもあるので省略します。

少し複雑なことをやろうとするとjQueryはすぐに読みにくくなってしまいますが、Reactならば直感的に書けます。 また、React用に用意されているリッチなコンポーネントライブラリも増えてきており、例えばこれをShinyで使えれば、既存の用意されているもの以外にも使えるデザインの幅が広がります。

というわけで reactR をご紹介します。 ただ、このパッケージはまだ開発が十分でないことをご留意ください。

reactRの作者について

reactRパッケージの作者は、@timelyportfolio さんです。 この方は可視化や地理空間情報分析に長けており、RとJavaScriptのプロフェッショナルという貴重なスキルセットをお持ちな方です。

以前紹介した「mapedit」「mapview」もこの方が開発に関わっており、個人的に目が離せない人物です。

ksmzn.hatenablog.com

ksmzn.hatenablog.com

簡単な使い方

では、使ってみましょう。

library(reactR)
library(htmltools)

x <- tagList(
  reactR::html_dependency_react(),
  tags$div(id = "example"),
  tags$script(
    HTML(
      reactR::babel_transform("
        const Hello = <h1>Hello, ReactR!</h1>
        ReactDOM.render(
          Hello,
          document.getElementById('example')
        )
      ")
    )
  )
)
browsable(x)

f:id:ksmzn:20171220030341p:plain

上記を実行すると、図のように「Hello, ReactR!」と表示されます。 簡単に言えば、tag を駆使してHTMLの骨格を作り、reactRの関数でreactを読み込んだりreactで書かれたJavaScriptコードを挿入しています。

reactRが提供する関数はたった2つです。

html_dependency_react

reactの htmltools::htmlDependency を作ってくれる関数です。 これにより、外部ライブラリであるreactをcdnを用いて読み込むことができます。 さきほどのコードを実行してできた画面のソースをみると、しっかりreactが <script> タグに挿入されています。

babel_transform

babelを用いてコードを変換してくれる関数です。 これにより、ES2015やJSXを用いてコードを書くことができます。 特にJSXは、Reactを書くときに欠かせないのでありがたいですね。

ちなみに、この関数の内部では V8 パッケージが使われています。 V8パッケージは、Google製のJavaScript実行エンジンをRから呼び出すパッケージです。

日本語の記事だと yamano357さんが既に活用していますね 。さすがです。

サンプル

reactRのレポジトリにはいくつかサンプルがあります。 それを読むと、html_dependency_react の内部を参考にhtmlDependencyを定義すれば、外部パッケージを読み込めるようです。

ということは、冒頭に書いたように、React用に提供されているライブラリも使うことが可能です。

例えば、MicroSoftが提供しているReact用UIライブラリ「office-ui-fabric-react」を使ってみると、

library(htmltools)
library(reactR)

fabric <- htmlDependency(
  name = "office-fabric-ui-react",
  version = "5.23.0",
  src = c(href="https://unpkg.com/office-ui-fabric-react/dist"),
  script = "office-ui-fabric-react.js",
  stylesheet = "css/fabric.min.css"
)

browsable(
  tagList(
    html_dependency_react(),
    fabric,
    tags$div(id = "app-button"),
    tags$script(HTML(babel_transform(
      '
      const btn = 
        <Fabric.DatePicker placeholder="Select a date..." />

      ReactDOM.render(btn, document.querySelector("#app-button"));
      '
    )))
  )
)

f:id:ksmzn:20171220031005g:plain

このような感じで、ライブラリが提供しているDatePickerが使えるようになりました。

まとめ

サンプル少なすぎてすみません。 本当はもっとリッチなものをつくりたかったのですが、 いくつかエラーにハマり、載せるクオリティのものが作れないまま時間切れとなりました。 なにか作ったら追記しますが、その前に解決すべきエラーが多そうです。 この分野は少しマニアックではありますが、 なかなか面白いので、もう少し深堀を続けるつもりです。

使いこなせるようになったら自作Shinyアプリに載せたいですね。

そうそう、reactと同じくらい人気のフレームワークである「vue.js」が使えるRパッケージ、「vueR」もあるそうですよ。残念ながら僕はvueを書かないので使う見込みはなさそうですが、vue派の人はぜひどうぞ。

エンジョイ。

RStudioアドイン「codicR」で酷い英語力による変数名をなんとかする

この記事は 「RStudio Advent Calendar 2017」 15日目のエントリーです。

こんにちは、皆さんは英語が得意ですか。私はもう駄目です。

それなのにコーディングなどをしているので、変数名とかカラム名を付けるときにいつも苦労します。僕が書いたコードを見せると、「この変数名はちょっと」という反応が返ることがよくあります。すみません。もう一度リーダブルコードを読み直せ。

そんなときには、 「codic」 にお世話になります。 このサービスはあちこちで紹介されているのでご存知かもしれませんが、 日本語を入力するとプログラミング向けの英語に変換してくれるサービスです。最高ですね。

そんな素敵なcodicですが、お世話になりすぎてしまい、いちいちRStudioからブラウザに切り替えるのも苦痛になってきました。ありがたいことにcodicでは API が公開されているので、RStudioから使えるアドイン 「codicR」 を作ってみました。

使うとこんな感じです。

f:id:ksmzn:20171211222943g:plain

例えば「リクエストを送る」という関数を作りたいけど英語が出てこないとき、このアドインを使えばすぐにナイスなイングリッシュにトランスレイトしてくれます。

インストール

GitHubからインストールしてください。

> devtools::install_github("ksmzn/codicR")

使い方

1 codic でアカウントを作り、ログインします。

2 APIステータス ページにトークンがありますので、コピーして CODIC_TOKEN として環境変数に入れます。Rでやるならこう。

Sys.setenv(CODIC_TOKEN='<your-token>')

3 RStudioで、変換したい日本語を選択状態にします。

4 Addins メニューから Translate by codic を押します。

5 英語に変換され、自動的に挿入されます。

ホクソエムを変換するとどうなるか

すごくどうでもいい話をしますが、ホクソエムという変数名をつくりたいなぁと思い試してみたところ、

f:id:ksmzn:20171211235226g:plain

_人人人人人人_
> ho_shit_m <
 ̄YYYYYY^ ̄

以上です。エンジョイ

参考:

notchained.hatenablog.com

shiny.i18nパッケージでshinyを多言語対応

このエントリは「R Shiny Advent Calendar 2017」の10日目の記事です。

みなさん、せっかく作ったshinyアプリを世界の人々に見せたいときってありますよね。ね。

先日、自作Shinyアプリを多言語に切り替えるパッケージとかないかなぁと探したところ、 「shiny.i18n」パッケージを見つけたので試してみました。

shiny.i18nパッケージのつかいかた

注意: できたばかりのパッケージらしく、以下の解説は古くなる可能性があります。

インストール

GitHubからインストールしましょう。

devtools::install_github("Appsilon/shiny.i18n")

言語切り替え

では、さっそく使っていきましょう。

当然ですが、言語を切り替えるにはその言語に対応した文言が用意されていなければなりません。 shiny.i18n パッケージは、言語ファイルとして csvjson のどちらかが必要です。

今回は、下記のような json ファイルで説明します。

{
  "languages": [
    "en",
    "pl",
    "jp"
  ],
  "translation": [
    {
      "en": "Hello Shiny!",
      "pl": "Witaj Shiny!",
      "jp": "こんにちは、Shiny!"
    },
    {
      "en": "Number of bins:",
      "pl": "Liczba podziałek",
      "jp": "binの数"
    },
    {
      "en": "This is description of the plot.",
      "pl": "To jest opis obrazka.",
      "jp": "プロットの説明"
    },
    {
      "en": "Histogram of x",
      "pl": "Histogram x",
      "jp": "xのヒストグラム"
    },
    {
      "en": "Frequency",
      "pl": "Częstotliwość",
      "jp": "頻度"
    }
  ]
}

まず、「languages」の項に対応したい言語名を列挙します。ここは後述の「translation」と同一である必要があります。今回は英語・ポーランド語・日本語です。先頭に書いた言語がデフォルトとして設定されます。

次に、「translation」で各文言に対する翻訳を記載します。わかりやすいですね。

では、このjsonを適当な所に置き、試してみましょう。 はじめはshinyでなく、コンソールで実行してみます。

shiny.i18nはクラスで実装されています。 まずはインスタンスを作る際に、先程のjsonファイルを指定します。

「translations」を見ると、先程の設定がデータフレームとなっています。 これをもとに、言語を切り替えるようです。

> library(shiny.i18n)

> # 読み込み
> translator <- Translator$new(translation_json_path = "./data/translation.json")

> # 対応表
> translator$translations
                                                    pl                 jp
Hello Shiny!                              Witaj Shiny! こんにちは、Shiny!
Number of bins:                      Liczba podziałek            binの数
This is description of the plot. To jest opis obrazka.     プロットの説明
Histogram of x                             Histogram x    xのヒストグラム
Frequency                             Częstotliwość               頻度

では、実際に文字列を出力してみます。 まずは、デフォルトの英語です。

文字列の出力は translate メソッドで行います。 ttranslate の単なるラッパーなので、より短く書けます。 英語の文字列がそのまま出力されていますね。

> translator$translate("Hello Shiny!")
[1] "Hello Shiny!"
> translator$t("Frequency")
[1] "Frequency"

では、言語を切り替えてみましょう。 set_translation_language メソッドを使って日本語にします。

> translator$set_translation_language('jp')
> 
> translator$translate("Hello Shiny!")
[1] "こんにちは、Shiny!"
> translator$t("Frequency")
[1] "頻度"

おお、きちんと対応する日本語になっていますね。 次はポーランド語にしてみます。

> translator$set_translation_language('pl')
> 
> translator$translate("Hello Shiny!")
[1] "Witaj Shiny!"
> translator$t("Frequency")
[1] "Częstotliwość"

こちらもしっかり表示できています。 元の英語にももちろん戻せます。

> translator$set_translation_language('en')
> 
> translator$translate("Hello Shiny!")
[1] "Hello Shiny!"
> translator$t("Frequency")
[1] "Frequency"

Shiny で使う

では、本題であるShinyで使ってみましょう。 パッケージのGitHubレポジトリにはサンプルがあり、そちらのソースをjsonを読むように変更しました。

こんな感じで切り替えできます。

f:id:ksmzn:20171209204102g:plain

shinyのソースはこちら(app.R)です。 reactive を用いて言語を切り替えています。

library(shiny)
library(shiny.i18n)

ui <- shinyUI(fluidPage(
  titlePanel('shiny.i18n'),
  uiOutput('page_content')
))

translator <- Translator$new(translation_json_path = "./data/translation.json")

server <- shinyServer(function(input, output) {
  
  i18n <- reactive({
    selected <- input$selected_language
    if (length(selected) > 0 && selected %in% translator$languages) {
      translator$set_translation_language(selected)
    }
    translator
  })
  
  output$distPlot <- renderPlot({
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins,
         col = "darkgray", border = "white",
         main = i18n()$t("Histogram of x"), ylab = i18n()$t("Frequency"))
  })
  
  output$page_content <- renderUI({
    tagList(
      sidebarLayout(
        sidebarPanel(
          selectInput('selected_language',
                      i18n()$t("Change language"),
                      choices = translator$languages,
                      selected = input$selected_language),
          sliderInput("bins",
                      i18n()$t("Number of bins:"),
                      min = 1,
                      max = 50,
                      value = 30)
        ),
        mainPanel(
          plotOutput("distPlot"),
          p(i18n()$t("This is description of the plot."))
        )
      )
    )
  })
  
})

shinyApp(ui = ui, server = server)

できたばかりのパッケージなので破壊的変更が起こる可能性はありますが、文言を切り替えたいときにはぜひ試してみてください。