Lesson 1-2: はじめてのRスクリプト

2018/09/28

前のステップ

Lesson 1-1: R を使ってみよう! では次のことを勉強しました。

このセッションの目標

前回実行したような簡単な計算を1回だけ行うのにパソコンを立ち上げるは必要ないかもしれません。しかし,ほとんどの仕事はもっと複雑なもので,

をしなければならない場面が現れます。このようなケースにはプログラミングが本領を発揮してくれます。

当然のことながら,やらなければならない処理が複雑になってくると

コマンドが長くてコンソールでは手狭になる

という問題が発生します。コマンドをファイルに記録する訳ですが,そうすると

ファイルが増えて管理が大変になる

という状態が到来するのは目前です。重要なファイルとそうでないファイルがごちゃ混ぜになって散らかってしまう前に,系統だった管理の方法を確認しておきましょう。その後,ファイルにコマンドを書いて実行する方法を説明します。

RStudio プロジェクト

RStudio にはプロジェクトを管理する機能があります。何か新しいことを始めようと思ったときには,まずプロジェクトを作成することをおすすめします。

Rプロジェクトを作る手順

RStudio のウインドウの右上角を見てください。下図のように “Project: (None)” となっているときは,どのプロジェクトも開いていない状態です。

Fig: プロジェクトを開いていない状態

Fig: プロジェクトを開いていない状態

“New Project…” をクリックして,プロジェクトを作りましょう。新しいプロジェクトをセットアップするためのウィザードが開始されます。

Fig: 新しいプロジェクト

Fig: 新しいプロジェクト

“New Directory” か “Existing Directory” のどちらかを選びます:

  • New Directory - プロジェクトのフォルダがまだない場合
  • Existing Directory - プロジェクトのフォルダをすでに作っている場合

ここでは “New Directory” を選びます。

Fig: プロジェクトタイプ

Fig: プロジェクトタイプ

次に “Project Type” を選ぶように促されますので,これは “New Project” を選んでください。

使用環境に応じて異なる表示をするかもしれませんが,おおよそ次のように表示されます。プロジェクトに相応しい英語の名前をつけましょう。“Directory Name” がプロジェクトの名前になります。ここでは “RClub” とします。(スクリーンショットに表示されている ~ は「ホームディレクトリ」を意味する記号です。詳しくは コラムを参照してください)

Fig: プロジェクト名

Fig: プロジェクト名

RStudio が新しく開くと,右上に “RClub” と表示されます。これでプロジェクトの作成は完了です。

Fig: プロジェクトに入っている状態

Fig: プロジェクトに入っている状態

練習 1
RStudio をすべて閉じてください。エクスプローラーで “RClub.Rproj” ファイルを探してダブルクリックします。RStudio が開いて,プロジェクトが開かれていることを確認してください。

プロジェクトの設定

プロジェクトに対する設定を確認しておきましょう。Files の書かれた枠に “RClub.Rproj” というファイルが見えているはずです。これをクリックしてください。

Fig: Files ペインの RClub.Rproj

Fig: Files ペインの “RClub.Rproj”

すると,次のような設定画面が表示されます。プロジェクトごとに設定を変えることができますが,基本的には以下の通りに設定することをおすすめします。

General タブ

  • Restore .RData into workspace at startup: No
  • Save workspace to .RData on exit: No
  • Always save history (even if not saving .RData): Yes
Fig: データはコマンド履歴のみ保存する

Fig: データはコマンド履歴のみ保存する

Code Editing タブ

Text encoding が UTF-8 になっていることを確認してください。

Fig: Text encoding は UTF-8

Fig: Text encoding は UTF-8

最初のRスクリプト .Rprofile

後ほど詳しく説明しますが,「スクリプト」というのはコマンドを書いたテキストファイルのことです。

.Rprofile というファイル(ファイル名の最初がドット,R だけ大文字)は特別なスクリプトで,プロジェクト・フォルダの直下に置いておくと,プロジェクトを開くたびに最初に実行されます。

練習 2
コンソールで次のコマンドを実行して,.Rprofile を作成してください。

> file.edit(".Rprofile")

内容は次のようにして保存します。ただし,“Kenji” のところはあなたの名前に変えてください。

# .Rprofile
message("Hello, Kenji! Today's ", Sys.Date(), ".")

問題 1
プロジェクトを再読み込みしてください。起動直後に .Rprofile が何をしたか説明してください。

R version 3.5.1 (2018-07-02) -- "Feather Spray"
Copyright (C) 2018 The R Foundation for Statistical Computing

.....(中略) .....

Type 'q()' to quit R.

Hello, Kenji! Today's 2018-09-16.    ← ココが増えた!

.Rprofile の置き場所

ホームディレクトリ(~, コラム参照)に .Rprofile (以下,~/.Rprofile)を置くように推奨している教科書もたくさんありますが,初心者のうちはプロジェクトフォルダだけに .Rprofile を書くようにしましょう。ホームディレクトリの ~/.Rprofile ファイルは遠くにある目に見えないファイルで「自分でさえ書いたことを忘れる」ことがよくあるからです。そんな,忘れがちなファイルであるにも関わらず,R はこれを毎回律儀に実行してしまうので,思いもよらぬ結果をもたらすことがあるのです。授業のレポートに R を使ってもらっていて,学生さんに「よく分からないエラーが出て困っている」と聞かれて調べてみると ~/.Rprofile が悪さをしていた,ということもありました。

このセクションで無害な .Rprofile を書いてもらったのには1つ重要な理由があります。これがあると,~/.Rprofile を無視するからです。別の講座や自習のために ~/.Rprofile を作った人がいても,そちらは読み込まれないようになっています。

もちろん,1つ1つのコードが何をやっているのかが分かるようになってきたら,害のない範囲で ~/.Rprofile を育てていくのはよい心がけでしょう。その場合でも,プロジェクトフォルダにも .Rprofile を作って,プロジェクトだけで必要なコードはプロジェクトの .Rprofile だけに書くようにします。最初の行を次のように書いておけば ~/.Rprofile も読み込んでくれます。

if (file.exists('~/.Rprofile')) sys.source('~/.Rprofile', envir = environment())

プロジェクト・フォルダの構成

標準的なデータ分析プロジェクトには,

  • コマンドを記録したファイル(ソースコード)
  • 生データ
  • 生データを処理して出来上がった2次データ
  • 分析結果を保存したテキストファイル
  • 分析結果のグラフ
  • ソースコードの使い方
  • 分析結果の解釈などを含めたレポート

などなどが必要になります。以下のように,ファイルの種類に応じたフォルダを作って整理しましょう。もちろん,必要に応じて増やしたり減らしたりしても構いません。

RClub/           (プロジェクト・フォルダ)
├── .Rprofile
├── README.Rmd   (後述)
├── Data/
├── Graphics/
├── R/
├── RClub.Rproj
├── Reports/
└── Results/

R上でフォルダを作るにはコンソールで次のコマンドを実行します(Files ペインやエクスプローラーを使っても構いません)。5つの空のフォルダができあがります。

> dir.create("R")
> dir.create("Data")
> dir.create("Results")
> dir.create("Graphics")
> dir.create("Reports")

そして,フォルダの内容物に関する規則を決めてしまいましょう。例えば次のように決めます。

フォルダ名 コンテンツ
R スクリプト(コマンドを書いたファイル)
Data データ(生データと前処理済の2次データ)
Results プロジェクトの出力(主にテキスト形式のもの)
Graphics プロジェクトで作成したグラフなど
Reports 分析の詳細と解釈などを記載したレポート

スクリプト

スクリプトというのはコマンドを並べたテキストファイルのことで,source() という関数を使うと,R はファイルに書かれたコマンドを上から順に実行していきます。このファイルには .R という拡張子をつけることが推奨されています。

スクリプトファイルは R フォルダに置きます。

新しいスクリプトを作るには

スクリプトを書いて実行する

スクリプト 1

ひとまず簡単な計算をするスクリプトを書いてみましょう。

> file.edit("R/calc.R")

テキストエディタが開きますので,そこにコマンドを打ち込んでいきます。 なんでもいいのですが,例えば次のようにしてみましょう。

# calc.R

5 + (8 + 9) * 12 - 30

最初の行の # calc.R というのは入力してもしなくても構いません。# から行の最後までは R は無視します。コードを説明するコメントを入力するときに使います

コード全体を実行するには少なくとも3つの方法がありますので,すべての方法を試してみてください。

  1. RStudio の Source ボタンを使う
  2. キーボードショートカット Ctrl+Shift+Enter (Win) / Cmd+Shift+Return (mac) を使う
  3. キーボードショートカット Ctrl+Shift+S (Win) / Cmd+Shift+S (mac) を使う
  4. source() 関数を使う。例:
> source("R/calc.R")

練習 3
calc.R を上の3つの方法で実行してください。違いがあれば,説明してください。

解説 source("R/calc.R") を実行しても何も表示されずに困惑したかもしれません。source() 関数は「結果を画面に出力しない」というのがデフォルトになっているからです。Ctrl+Shit+S も同じように振る舞います。

Ctrl+Shit+Enter は「『結果を画面に出力する』というオプションをオンにした source() 」です。echo というのがそのオプションの名前です。

> source("R/calc.R", echo = TRUE)

echo = TRUE とすると途中の計算もすべて表示されてしまうので,source("calc.R") を使って最終結果のみ表示したいというケースが多々あります。そういう場合には結果を明示的に画面に表示するようにスクリプトを書き変える必要があります。 print() という画面に出力するための関数を使います。

# calc.R (edited)

print(5 + (8 + 9) * 12 - 30)

スクリプト例 2

問題 2
次の計算をしなさい。

\[ 1 + \dfrac{1}{ 1 + \dfrac{1}{ 1 + \dfrac{1}{ 1 + \dfrac{1}{ 1 + \dfrac{1}{ 1 + \dfrac{1}{ 2 } } } } } } \]

読みやすさを考慮して半角スペースや改行を適切に挿入します。

1 + 1 / (
  1 + 1 / (
    1 + 1 / (
      1 + 1 / (
        1 + 1 / (
          1 + 1 / (
            2
          )
        )
      )
    )
  )
)
## [1] 1.619048

開いた括弧の後ろで改行していることに注意しましょう。中途半端な感じがするかもしれませんが,中途半端だからこそよいのです。例えば,

1 + 1
/ (
  1 + 1 / 2
)

を実行しようとすると,

Error: unexpected '/'

というエラーで止まってしまいます。1行目が完結したコマンドになってしまっているので,R は全体を1つのコマンドとは認識せず, / から始まる2つ目のコマンドを実行しようとします。割り算の記号 /A / B の形でしか使えないのでエラーになります。

スクリプト例 3

問題 3
次のスクリプトを実行したときに何が起こるかを予想してください。その後,実際に作成・実行して予想が正しかったかどうかを検証してください。

# exponential.R

png("Graphics/exponential.png", height = 1440, width = 1440, res = 216)
plot(exp)
dev.off()

解説 Graphics フォルダに exponential.png という画像ファイルが生成されます。画像は前回学んだ指数関数のグラフです。

png("保存フォルダ/ファイル名.png", 種々のオプション)dev.off() の間に実行された描画は,指定したファイルに保存されます。この機能を使えば,論文やレポートを作成するときに必要なグラフを R で作ることができますね。

png 以外にも pdf などにも保存することができます。(オプションは保存形式によって異なります)

なぜスクリプトを書くのか?

ここで紹介したような短い例では,スクリプトは役に立たないと思うかもしれません。しかし,そうとも限りません。 スクリプトはコンピュータにコマンドを命令するための指令書であると同時に,未来の自分(あるいは他人)が,分析手順の正しさを検証するために必要になります。

グラフ1つとっても「どうやって描いたのか?」ということを問われるケースもあります。Excel でグラフを作るときに実行する複雑な手作業を記憶することは困難でしょう。しかし,R をはじめとしたプログラミング言語では,グラフの微調整を手作業ではなくコマンドを通して行うので,記録が簡単になるというところにあります。スクリプトを保存しておけばよいのですから。

簡単な作業であっても,分析の記録という観点からスクリプトを活用することをおすすめします。

コメント

なぜコメントを書くのか?

次の2コマ漫画は ボズウェル・フォシェ・角征典訳(2012)『リーダブルコード』(The Art of Readable Code)オライリーからの引用です(訳書 p. ix)。

Fig: Readable Code

Fig: Readable Code

「こんなことがあるはずない」と思うかもしれませんが,実際によくあることです。昔々の経験を思い出すとくすっと笑えるのですが,「2週間後の私」には面白くない冗談かもしれませんね。結局イチから書き直したり・・・・・

要するにそういうことが起こらないように

  • コメントをしっかり書きましょう
  • 名前は適切に付けましょう(後述)

ということです。本格的なコードを書き始めたときに重要になるので,覚えておいてください。

R 言語で書かれたコードを実行するプログラム(インタプリタという)は半角のハッシュ(#)からその行の最後までを読み飛ばします。書かている内容が「コメント」です。コメントは人間が読むためのものなので,そこに書いた内容は実行結果には影響しません。

問題 4
次のコードの出力は何になるでしょうか?

# ここはコメント
# 複雑なコードを説明したり
# スクリプトの目的などを書くとよいでしょう

log(1)   # ここもコメント

## [1] 0

RStudio のセクション機能

スクリプトを実行する際にはコメントは読み飛ばされますが,RStudio や一部のRパッケージはコメントを利用して便利な機能を提供しています。

ここでは,RStudio のセクション機能 を簡単に紹介しておきましょう。

RStudio は

  • # (ハッシュ)
  • セクション名
  • 半角スペース
  • -, =, # のどれか1つを4つ以上続けて書く

をこの順で並べるとセクションの始まりと認識します(実際のルールはもう少し緩やかなものです)。セクションの終わりは

  • ファイルの終わりか,
  • 次のセクションが始まる直前です。

なぜこのような機能がありがたいかを理解するために,次のようなスクリプトを書いてみましょう。

> file.edit("R/sections.R")
# sections.R

# Section 1 ####

log(10)

# Section 2 ====

stop("Error")

# Section 3 ----

message("Hello")

これを source() すると…

> source("R/sections.R", echo = TRUE)

次のような結果になります。

> # sections.R
> 
> # Section 1 ####
> 
> log(10)
[1] 2.302585

> # Section 2 ====
> 
> stop("Error")
Error in eval(ei, envir) : Error

Section 2 の直後にエラーが出ているので,Section 3 の内容が実行されていないことが分かると思います。もし,コード全体の実行しかできなければ,次のような不便があります。

  • Section 2 のエラーは後回しにして,Section 1 の作業をするときには,実行のたびに Section 2 が実行されてエラーが起きるので鬱陶しい。
  • Section 2 のエラーは後回しにして,Section 3 の作業をするときには,Section 3 は実行されない。
  • Section 2 のエラーを解決しようと思って作業するときにも,Section 1, 3 が実行されてしまうのでやっぱり鬱陶しい。

したがって,セクションごとにコードを実行できる機能があると大変便利なわけです。

RStudio のナビゲーションメニューから

  • Code > Run Region > Run Code Section

を探してみてください。Windows では Ctrl+Alt+T がショートカットキーとして割り当てられていることが分かりますので,これを覚えてしまいましょう。(mac では Command+Option+T)

  • セクションを作るには, コメントだけからなる行を作って最後に ====, ----, または #### をつける
  • セクションのコードを実行するには,セクション内にカーソルがある状態で Ctrl+Alt+T (Command+Option+T) を押下する

まとめ