株式会社ホクソエムのブログ

R, Python, データ分析, 機械学習

クロネッカー積でデータを列方向(or行方向)に高速に複製もしくは定数倍する

r-wakalangからの転載です。以下のような質問がありました。

data.frameをカラム・ロウ方向に複製結合したdata.frameを出力させたいのですが、どうも綺麗に書けずです。。アドバイスお願いしますm( )m

この意味は、例えば「行方向に2個・列方向に3個複製」の場合は以下の図です。

f:id:StatModeling:20180824174855p:plain

データフレームが数値のみの場合、これは実はクロネッカー積と呼ばれる行列の特殊な積で表現できます。

  • Rで書く場合

Rではデフォルトで%x%関数(or kronecker関数)が用意されているのでそれを使えば簡単に実装できます。

B <- as.matrix(data.frame(a=1:3, b=4:6))
A <- matrix(1, nrow=2, ncol=3)
res <- A %x% B
  • Pythonで書く場合

Pythonでもnumpykronメソッドが用意されていますので、以下のように書くことができます。

import pandas as pd
import numpy as np

B = pd.DataFrame(np.arange(1,7).reshape(2,3).T, columns=list('ab'))
A = pd.DataFrame(np.ones((2,3)))

kp = pd.DataFrame(np.kron(A,B), columns=pd.MultiIndex.from_product([A,B]))

  * * *  

定数倍も行けます。例えば、以下のように

f:id:StatModeling:20180824163606p:plain

左のデータフレームから右のデータフレームが得たい場合です。

  • Rで書く場合
A <- as.matrix(data.frame(a=1:3, b=4:6))
B <- matrix(1:50, nrow=1)
res <- A %x% B
  • Pythonで書く場合
import pandas as pd
import numpy as np

A = pd.DataFrame(np.arange(1,7).reshape(2,3).T, columns=list('ab'))
B = pd.DataFrame(np.arange(1,51).reshape(1,50))

kp = pd.DataFrame(np.kron(A,B), columns=pd.MultiIndex.from_product([A,B]))

Enjoy!

ggplot2 で時系列の区間に影をつけるのは annotate が便利ぽい

例えば次のような時系列データがあるとします。

library(xts)
ts <- as.xts(Nile)

library(ggplot2)
autoplot(ts)

f:id:hoxo_m:20180821233320p:plain

このプロットの 1900年から1940年までの区間に影をつけたい。

これには annotate() が便利ぽい。

autoplot(ts) + 
  annotate("rect", 
           xmin = as.Date("1900-01-01"), 
           xmax = as.Date("1940-01-01"), 
           ymin = -Inf, ymax = Inf, alpha = 0.2)

f:id:hoxo_m:20180821233547p:plain

Enjoy!

参考

RStudioServer から ShinyApp を直接デプロイしたい

現在 CentOS 7.5 サーバーに RStudioServer と ShinyServer を入れて RStuidio 上で ShinyApp を書いています。

デプロイするには /srv/shiny-server/ の下にフォルダを丸ごとコピーしていますが、サーバにいちいちログインするか RStudio の新機能である Terminal 上でコピーしちゃうんですが、これを R でやりたいというのが今日のお題です。

適当に書くと次のようになると思います。

deploy_shiny_app <- function() {
  # 現在のワーキングディレクトリに ShinyApp があるとする
  dir_path <- getwd()
  # ShinyApp のデフォルトのデプロイ場所は /srv/shiny-server/
  target_dir_path <- file.path("/srv/shiny-server", basename(dir_path))
  # ShinyApp のフォルダにある .R ファイルを全て取得
  files <- list.files(dir_path, pattern = "\.R$", full.names = TRUE)
  # sudo cp コマンドで全てコピー
  command <- sprintf("sudo cp -vfu %s %s", paste(files, collapse = " "), 
                     target_dir_path)
  system(command, input = rstudioapi::askForPassword("Enter password"))
}

rstudioapi::askForPassword() というのはコード上にパスワードを平打ちしたくない時にこれ書いとくと RStudio 上でパスワードを入力するプロンプト出してくれるナウいやつです。

さて、これを実行すると次のようなエラーが出ました。

sudo: no tty present and no askpass program specified

これはなんかセキュリティ的な制限で、デフォルトでは sudo 時のパスワードが表示されないようにしてるみたいです。 解除するには

$ sudo visudo

で sudoers ファイルを開いて

Defaults visiblepw

と書くと良いらしいです。

さて、これで実行するとうまくコマンドが実行されるわけですが、デプロイ先のフォルダがないとエラーが出てコピーできません。 なので、フォルダがなければ作るということをやります。

sudo_create_dir_if_not_exists <- function(dir_path) {
  if (!dir.exists(dir_path)) {
    command <- sprintf("sudo mkdir %s", dir_path)
    prompt <- sprintf("Create %s", basename(dir_path))
    system(command, input = rstudioapi::askForPassword(prompt))
  }
}

deploy_shiny_app <- function() {
  # 現在のワーキングディレクトリに ShinyApp があるとする
  dir_path <- getwd()
  # ShinyApp のデフォルトのデプロイ場所は /srv/shiny-server/
  target_dir_path <- file.path("/srv/shiny-server", basename(dir_path))
  # なければ作る
  sudo_create_dir_if_not_exists(target_dir_path)
  # ShinyApp のフォルダにある .R ファイルを全て取得
  files <- list.files(dir_path, pattern = "\.R$", full.names = TRUE)
  # sudo cp コマンドで全てコピー
  command <- sprintf("sudo cp -vfu %s %s", paste(files, collapse = " "),
                     target_dir_path)
  system(command, input = rstudioapi::askForPassword("Enter password"))
}

これでうまくいきそうなもんですが、ShinyApp の静的ファイルを www に入れたりモジュールをサブディレクトリに保存していたりという場合が考えられます。 なので指定したサブディレクトリもコピーするという記述も付け加えます。 このとき、フォルダからフォルダへコピーするという動作は共通なので関数化しちゃいます。

copy_files <- function(dir_path, target_dir_path) {
  # なければ作る
  sudo_create_dir_if_not_exists(target_dir_path)
  # ShinyApp のフォルダにある .R ファイルを全て取得
  files <- list.files(dir_path, pattern = "\\.R$", full.names = TRUE)
  # sudo cp コマンドで全てコピー
  command <- sprintf("sudo cp -vfu %s %s", paste(files, collapse = " "),
                     target_dir_path)
  system(command, input = rstudioapi::askForPassword("Enter password"))
}

deploy_shiny_app <- function(dir_path = getwd(), dest = "/srv/shiny-server") {
  # ShinyApp のデプロイ先
  target_dir_path <- file.path(dest, basename(dir_path))
  # コピーの実行
  copy_files(dir_path, target_dir_path)
}

コピーすべき subdir も指定可能にして for 文で回します。

deploy_shiny_app <- function(dir_path = getwd(), dest = "/srv/shiny-server", 
                             subdir = c("www")) {
  # ShinyApp のデプロイ先
  target_dir_path <- file.path(dest, basename(dir_path))
  # コピーの実行
  copy_files(dir_path, target_dir_path)
  
  # サブディレクトリのコピー
  for (subdir_name in subdir) {
    subdir_path <- file.path(dir_path, subdir_name)
    if (dir.exists(subdir_path)) {
      target_subdir_path <- file.path(target_dir_path, subdir_name)
      copy_files(subdir_path, target_subdir_path)
    }
  }
}

これで多分うまくいきます。 最初デプロイ先のフォルダがない場合はフォルダの作成、サブフォルダの作成とパスワードを何度も聞かれてうざいですが、まあしょうがないかなと。

もっと良い方法があれば教えてください。

Enjoy!

雑記

こんにちは、ホクソエムです。雑記です。

今では当たり前のように使われている pipe演算子こと %>% 。

dplyrパッケージが発表された当初は「気持ち悪い」と評判だったのですが、みなさんもう慣れたのでしょうか。

そしてrlistパッケージの %>>% 。

%>% よりハヤイ!!!!と当時は盛り上がっていましたが誰か使っている方はいるのでしょうか(私は使っていない)。 私が知らないだけで%>>>%とか%>>>>%とかあるのかもしれません。 「私はこんなpipe類似演算子を使っているよ!!!」というご報告お待ちしております。

最後に、pipeを使いたくない方にpipeを使ったコードを従来の表記に戻してくれるパッケージも開発されていましたが、皆さんこちらはご存知でしょうか。

https://github.com/TobCap/demagrittr

どんなものにも歴史はあるもので、流行っているその時にしか味わえない現在性を堪能することも、技術を追いかける醍醐味です。 言語開発の片隅に咲いたそんな一輪の花たちをこれからもお伝えしていきたいと思います。

Rユーザ会でStanの紹介と応用事例について話しました

Rユーザ会@統計数理研究所で「StanとRでベイズ統計モデリング」について発表しました。資料は以下です。

Rには詳しいがStanをほとんど知らない人たちへのStan紹介と、(空間)統計モデリングに詳しい人たちへのちょっと凝った応用事例の二部構成にしたため、易しい部分とかなり難しい部分のどっちつかずの内容になりました。ありがち。藤野さんをはじめとする皆様、ありがとうございました!

最後の参考文献のところにあるリンク先は以下になります。

Enjoy!

awe.s3パッケージでRからのAWS S3とのファイルやりとりを行う

ドーモ。ホクソエムです。更新が久しくなってしまいました。ホクソエムでは現在、Amazon Web Service (AWS)を利用していないのですが、本職の方でS3に触れる機会があったので、RからS3への操作を行うためのパッケージ awe.s3 を紹介したいと思います。

ASW S3とは、AWSが提供するサービスの一つで、オンラインでのファイルストレージとして利用できます。ストレージするファイルの容量・種類は問わないので、一時的なデータや画像の保存先として使われているのではないでしょうか。また、柔軟にアクセス制限やファイルのライフサイクル(自動的な削除)がかけられるのも特徴です。S3では、バケットと呼ばれるフォルダのような構造と、オブジェクト(データ)を管理します。

awe.s3パッケージは、数多くの便利なRパッケージを行っているROpenSciのメンバーでもあるThomas J. Leeperらが活動するcloudyrというRのチームが開発しています。cloudyrのリポジトリには、今回紹介するawe.s3のほか、同じAWSのサービスであるES2管理やLambdaのためのaws.ec2aws.lambdaなども含まれています。

github.com

awe.s3はCRANに登録されていますので、次のコマンドでインストールしましょう。また、S3の操作に必要なアクセスキーとIDは、IAM (Identity and Access Management) Management Consoleから発行しておいてください。

install.packages("aws.s3", dependencies = TRUE)

library(aws.s3)

アカウントとの紐付け

早速、ストレージしたファイルへのアクセスを行いたいところですが、まずはアクセスキーIDとシークレットキーを使った認証を行うことが必要です。

cloudyrが携わるAWS関係のRパッケージでは、Sys.setenv()で設定されている環境変数を利用します。これらが.Rprofile等に記載されていない場合は、コンソールでSys.setenv()を行いましょう。必要な情報は、アクセスキーID、シークレットキー、利用しているリージョン(地域)です。

# 環境変数の値を確認
Sys.getenv("AWS_DEFAULT_REGION")
# [1] ""

Sys.setenv("AWS_DEFAULT_REGION" = "<リージョン>", # us-east-2 など
           "AWS_ACCESS_KEY_ID" = "<アクセスキーID>",
           "AWS_SECRET_ACCESS_KEY" = "<シークレットキー>")

複数アカウントがある場合、AWSの発行するcredentialsファイルを使った署名を行うこともできます。これにはawe.s3インストール時に依存パッケージとしてインストールされるaws.signatureuse_credentials()を使います。

# defaultのアカウント情報を用いた署名
aws.signature::use_credentials()

# hoxouri ユーザのアカウント情報を利用する場合
aws.signature::use_credentials(profile = "hoxouri")

接続が成功しているかを確かめるため、バケットの一覧を表示してみます。

bucketlist()
#              Bucket             CreationDate
# 1 aws.s3.test170418 2017-04-18T04:35:22.000Z
# 2        hoxom-blog 2017-07-18T11:02:47.000Z

うまくできているようですね。

特定のバケットのオブジェクトを出力するにはget_bucket()を使います。

get_bucket("aws.s3.test170418")
# Bucket: aws.s3.test170418 
# 
# named list()

どうやらこのバケットにはまだ何も入っていないようです。

オブジェクト操作

それでは、バケットに対してオブジェクト(データ)を保存したり、バケット内のオブジェクトへの操作を行いましょう。awe.s3では、次のようなオブジェクト操作が可能です。

  • Rオブジェクト(.Rdata, .rds)の読み書き (s3save(), s3saveRDS())
  • R関数を使ったRへの読み書き (s3read_using(), s3write_using())
  • ローカルファイルのバケットへの保存 (put_object())
  • バケットからのローカルへの保存 (get_object())
  • バケット、オブジェクトの削除 (delete_bucket(), delete_object())

例として、mtcarsオブジェクト(データフレーム)をS3に保存します。Rオブジェクトとして保存したい時はs3save()で行います。

s3save(mtcars, bucket = "aws.s3.test170418", object = "mtcars.rds")

第一引数で対象のRオブジェクト、第二引数で対象のバケット名、第三引数のobject引数ではオブジェクト名を与えます。関数の実行後、コンソールには何も表示されませんが、エラーがでなければアップロードは成功しているはずです。改めてバケットの中身を出力してみましょう。

get_bucket("aws.s3.test170418")
# Bucket: aws.s3.test170418 
# 
# $Contents
# Key:            mtcars.rds 
# LastModified:   2017-07-18T11:33:04.000Z 
# ETag:           "1bf2269b855ca97b628582dc29962eb1" 
# Size (B):       1235 
# Owner:          suika1127 
# Storage class:  STANDARD

次はcsvをアップロードする例です。Rオブジェクトではなくcsvなどのファイルで保存したい時はreadr::write_csv()などの関数を使いテキストファイルにしておきましょう。またその際はput_object()を使い、ファイルのアップロードを行います。

mtcars %>% 
  readr::write_csv("sample_mtcars.csv")
put_object(file = "sample_mtcars.csv", 
           object = "sample_mtcars.csv", 
           # バケットにはフォルダを作ることができますが、bucket引数で指定(なければ作成される)できます
           bucket = "aws.s3.test170418/csv")

今度は保存したオブジェクトをRで利用可能な状態にします。対象がRオブジェクトであればs3loadreadrreadxlで読み込めるファイルであればs3read_using()を用います。

s3load("mtcars.rds", bucket = "aws.s3.test170418")
ls()
# [1] "mtcars"

s3read_using(readr::read_csv, object = "sample.csv", 
             bucket = "aws.s3.test170418/csv")

rdsファイルに保存したmtcarsオブジェクトが利用できるようになりました。

私も使い始めたばかりで、aws.s3パッケージの全てを紹介しきれませんが、基本的なことはできたかと思います。つどコンソールを叩かず、集計結果等を保存できる、データを引っ張ってこれるので便利ですね。

Enjoy!

RStudioアドイン 10選

Rユーザのみなさん、RStudio使っていますか。RStudioを使うなら、RStudioアドインも使いましょう。便利です。

… でも、\どんなアドインがあるのかわからない!

という声をしばしば聞きます。というわけでお気に入りのアドインを10個まとめました。用途ごとに部門を設けて紹介します。

RStudioアドインとは

そもそもRStudioアドインとは何か。それを説明しておかないといけませんね。

RStudioアドインとは、0.99.878以降のバージョンで実装されているRStudioの一機能です。複雑な処理をボタン一発で実行したり、ショートカットとして利用したり、GUI操作で処理を実行できるようになります。

RStudioアドインはメニューバーの「Addins」というボタンあるいは設定されたショートカットから呼び出すことができます。アドインは、Rの関数と同様にパッケージによって提供されているため、該当のパッケージをインストールすることで利用可能になります。

使い方やアドインの作成方法は公式のドキュメントまたはこちらの記事 (RStudioで気軽にLGTM)をご覧ください。

それではおすすめアドインの紹介に入ります。実用、可視化、文書作成、ネタ系の4つに分けます。簡単な説明と動作画像を貼りますので雰囲気を感じてください!カッコ内でアドインが含まれるパッケージを表示しています。

実用系

Rを使った作業一般で役立ちそうなアドインです。こちらからは5つ。

Reformat R Code (addinexamples)

適当なスペースはコードの可読性を高めます。GoogleもHadley Wickhamも演算子の後にはスペースを含めることを推奨しています。

このアドインは、選択したコードの可読性を高めるために実行することができます。具体的には、先の演算子間のスペースの自動挿入と、インデントの調整、一行のコードを任意の長さで改行するという機能をもちます。背景の処理にformatrパッケージが使われています。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_1.gif?raw=true

pipefittr (pipefittr)

見やすいコードにするためには、どんどんmagrittrパッケージのパイプ演算子を使うと良いです。でも古いコードなど、パイプが使われていないものもあります。そういった場合にこのアドインが役立ちます。このアドインは従来の、複数の関数の処理を入れ子で記述したコードをパイプ処理での書き方に直します (時々失敗してしまうのが玉に瑕)。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_2.gif?raw=true

Render reprex (reprex)

GitHubやStackOverflowなど、自分の環境で発生した状況を説明するには、言葉だけで再現性を成立させることはできません。やはり、状況を引き起こしているコードがなければいけません。ですが実際は、質問をあげる多くの人が問題の記述だけでコードを書きません。この問題を解決するのに大きく役立つのがreprexパッケージです。このパッケージは、GitHub、StackOverflowにRコードと実行結果をコピーできる状態で出力する関数を備えていますが、アドインとしてもその機能を実行することが可能です。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_3.gif?raw=true

対象を、コピーされているコードか、現在の選択範囲か、Rファイル全体かといったものを選んで実行できます。

なおこのパッケージの使い方は、こちらのブログ記事にも書かれています。ちなみにパッケージ名にもなっているreprexはreproducible exampleの略だそうです。再現性、大事!

tidydata (tidyshiny)

こちらのアドインは、現在ワークスペースにロードされているデータを対象にtidyr::gather()を実行する関数です。列の除外指定ができないようですが、コードが吐き出されるのでそれを編集すれば良いですね。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_4.gif?raw=true

githubinstall (addin4githubinstall)

GitHub上のパッケージをインストールするにはgithubinstallパッケージ一択ですが、適当なキーワードでパッケージを探したい…。そんな時が、あると思います!そこで役立つのがこのアドインです。キーワードを入力して、パッケージのリストから検索・インストールすることができます。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_5.gif?raw=true

こちらのアドインは

githubinstallが提供しているものでなく、こちらのリポジトリからパッケージをインストールして利用します。

可視化系

続いてプロットや何かの色を決めるのに便利なアドインを2つ。

colourPicker (colourpicker)

プロットで使われている色を変更したいけどカラーコードなんて覚えていない…。カラーピッカーというアドイン名の通り、色を表示しながら選択するのにこのアドインが便利です。同色の色のパターンも生成することができます。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_6.gif?raw=true

さらにこのパッケージでは、下記画像のようにプロットされた画像で使われている色を選択・変更可能なアドインも提供されています。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_colourpicker.png?raw=true

なお、shinyjsパッケージでも同じアドインが提供されていましたが、現在はcolourpickerパッケージとして独立したようです。そちらを使いましょう。

ggplot Theme Assistant (ggThemeAssist)

ggplot2の図は各種の要素に対して変更を加えることが可能です。しかし自由度が高いぶん、覚えるのが困難でもあります。このアドインは、その問題を解決します。

既存のggplot2でのプロットを実行するコードを選択した状態でアドインを実行すると、各要素を変更するためのGUIが起動します。あとは煮るなり焼くなり。お好みの図に調理して、コードを出力しましょう。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_7.gif?raw=true

文書作成 (rmarkdownまわり)系

Rmd形式のファイルで効果的なアドインを2つ。この他にも論文執筆の際の文献管理に役立つアドインやblogdown、bookdownなどでボタン一発ビルドを実行するアドインなどがあります。

Word count (wordcountaddin)

選択中のコードに含まれる単語数などを数えて出力します。日本語だと精度が高くないですが、読み終わる時間の目安も出ます。文章を書いている際に良いのではないでしょうか。

f:id:u_ribo:20180815193850g:plain

ちなみにMacで利用する場合、Javaのバージョンでエラーになることがあるかもしれません。その際は次の記事にあるコードを実行することで解決する可能性があります。

WrapRmd

RMarkdown内で実行するRコード(インラインコード)の改行を、レンダーに影響を与えずによしなにしてくれるアドインです。パッケージはCRANに登録されていないのでGitHubからインストールしてください。

f:id:u_ribo:20180815194055g:plain

ネタ系

最後にとっておきのアドインを紹介します。

Add gifs (giphyr)

Rの作業に疲れた時、ネコに癒されたくなった時、Shia LaBeoufに喝を入れてもらいったくなる時… そんな時にオススメのアドインです。

このパッケージはGiphyAPIを利用し、おもしろGifを取得するものです。アドインとして、画像の検索機能、貼り付け先や保存先を選べます。

https://github.com/HOXOMInc/blog/blob/master/docs/img/rs_addins_top10_10.gif?raw=true

ここに挙げた以外にも、みなさまオススメのアドインがございましたらホクソエムhoxom_incまでご一報ください!

Enjoy!