- このコードは何をしたいんだ……(自分で書いたはずなのに)
- この数字はどういう意味だ……(自分で書いたはずなのに)
- あのファイルはどこにあるんだったか……
もらったコードのサンプルをいじって最低限の解析をする。でも、コードが読みにくくて仕方がない。そういう研究者は少なくありません。工学系/IT系のバックグラウンドでもない限り、系統だってプログラミングを勉強したことがない人も多い(はず)です。
コードを他人と見せ合うこともあまりありません。コードを見てもらっても、全体としてあっているかを確認してもらう程度で、読みやすさについてのフィードバックはほとんどないのではないでしょうか。
私は自分が筆頭著者になった論文の解析は主に自分でやってきました(統計学者に大いに助けてもらっており、彼ら/彼女らなしではできませんでしたが、ベースとなる解析は自分でやりました)。しかし、ひとさまにお見せできるようなコードでは決してありません(恥)。改善したいと思ってきました。しかし、周囲を見渡してもR言語のわかりやすい書き方について系統立てて指導してくれる人はいませんでした。
わかりやすいコードを書けるようになるために、関連書籍やブログなどを調べました。非技術者である自分にわかった範囲で、徐々にコードを改善しています。道半ばですが、本記事では自分がR/Rstudioを始めるときに知っておきたかったことをまとめました。
本記事を読めばR生活が少しだけ整理されたものになるでしょう。
なお、著者はRユーザーとしては素人に毛が生えた程度で、2024年12月時点でgitも使えません(いずれ勉強したい……)。上級者には参考にもならないと思います(もっとよい方法があると思うので、よろしければぜひ教えて下さいm(_ _)m)。
R projectを使ってworking directory問題から解放される
RStudioを使い始めたときに私がまずストレスを感じたのがworking directoryなるものです。working directoryをどこにするか決めてset working directoryしなくてはいけなくて、パスに日本語が含まれているとエラーが起きるかもしれなくて……。中には解析を始める前に挫折する人もいるのではないでしょうか。
R projectを使えばworking directory問題から解放されます。方法は簡単で、RStudio > File > New Projectから設定します。(途中でgit repositoryを作成するか聞かれる場合は、gitを使わないのであれば作成しなくてよいとの認識です)フォルダ内のR projectファイルをクリックしてRStudioを起動すると、そのファイルが置かれているフォルダが自動的にworking directoryとして認識されます。これを使うことで他者にコードを渡してもworking directoryでごちゃごちゃせずにすむようになります。いつもproject_name.RprojファイルからRStudioを起動するようにしましょう。
RStudioのインストールでてこずってしまう場合、Posit cloud (RStudio cloud) を使うのも手です
フォルダ構造を整理する
解析するデータ、解析コード、出力画像のすべてが同じフォルダ内にぐちゃぐちゃにおいてある(さらにはそれぞれさまざまなバージョンがあって……)。私はそうでした。同僚のフォルダを見て下記のように改善しました。絶対的なルールがあるわけではありませんが、一貫性のあるルールを採用して使い続けることが大事です。
R_project_directory
├─README.md
├─data
│ ├─raw
│ └─processed
├─utils
│ ├─00_prepare.R
│ ├─01_clean.R
│ ├─02_analyze.R
│ └─appendix.R
└─outputs
- README.md
プロジェクト全体の目的・インプット・処理・アウトプットの説明とそれぞれのフォルダ内の説明を書き残します。
- ./data/フォルダ
データ置き場です。さらにサブフォルダーに分けて、生データ置き場と中間データ置き場に分けます。生データは常にそのままおいておくようにします。中間データ置き場には、最終成果物として使う訳ではないが他の処理などで使うものをおいておきます。生データの前処理が済んだものなど。
- ./outputs/フォルダ
最終論文やAppendixで使う画像などのデータ置き場。ファイルの数によってさらにフォルダ分けをします。
- ./utils/フォルダ
Rスクリプト置き場。
名前の付け方にも一定のルールを作りましょう。
フォルダ名は複数名詞か集合名詞にします。単数形を使う流派もあるようですが、データベースで「テーブル名は複数名詞か集合名詞」とするようなのでそれに倣うことにしました。(複数名詞か集合名詞が絶対的に正しいというわけではなく、一貫性があればよいと思います)
ファイル名はsnake_case(後述)を使います。
順番に実行するファイルには接頭辞 01_, 02_, … をつけましょう。
日付でバージョン管理する場合は_YYYYMMDDと接尾辞をつけことにします。アメリカやヨーロッパ式と混在させないようにします。日常生活ではDDMMYYYYを使うヨーロッパ人でも、ファイル名ではYYYYMMDDを用いていることが多いようです。(名前でソートすることを考えると当然そうなりますよね!MMDDYYYY? は本当に何を考えているんだか)
命名規則を決める
- 他人が理解するのに必要な時間を最小にする
- 誤解の余地を最小にする
というのが命名規則の目的です。命名規則を決めると、命名の方向性が定まり、迷いが減るというご利益もあります。様々な命名規則を参考に、2024年12月時点で採用している規則を紹介します。
- アメリカ英語を使う
- できるだけ具体的な表現をする
- 原則省略しない
- 単位がわかるように接尾辞をつける
- マジックナンバーを使わない
- アメリカ英語を使う
将来的に海外の共同研究者とコードを共有することがありえます。論文公表時にはコードを開示する傾向にあるので、英語でわかる表現にすることが大事です。綴りはイギリス英語でもよいですが、統一するようにしましょう。
- できるだけ具体的な表現をする
中間データをdf2などと命名するよりも、df_sd_imputedなどどのような処理がされた後のものかわかるような表現をしましょう。
- 原則省略しない
コードを書いているときには省略したくなりますが、後から読むと何の省略かわからなくなることがあります。n, sdなどの頻用統計用語、df(dataframe)は例外としています。
- 単位がわかるように接尾辞をつける
例えばdurationでは時間単位なのか、日にち単位なのか、週単位なのかわかりません。単位を語尾につけて、duration_hours, duration_days, duration_weeksなどとすることでわかりやすくなります。
- マジックナンバー(ベタ書き数字)を使わない
ベタ書きされた具体的な数字をマジックナンバーと呼ぶそうです。コードを書いているときは自明でも、後から読み直すときや修正するときのことを考えると、わかりやすい変数名を与えてあげるほうがよいそうです。はじめて言われたときは何がありがたいのかよくわかりませんでしたが、徐々にありがたみがわかってきました。
変数名はsnake_case(小文字とアンダーバーの組み合わせ)、関数名はPascalCase(頭文字は大文字でつなげる)を使う。他にもcamelCase, kebab-caseなどさまざまな書き方がありますが、snake_caseとPascalCaseを使うことにします。
プログラミング言語によって主に使うものが異なるらしいです
原則全てsnake_caseを用いるのがR言語では主流になってきているようですが、ひと目で区別できる方が便利だと思いこちらを採用しました。どれが正解というわけでもなく、ここでも一貫性が大事です。
テンプレを使う
スクリプトごとに下記のテンプレを使うようにして、どこに何が書いてあるかわかるようにします。特に、Purpose, Input, Outputをきちんと書くことでコードを書く際の方向性が定まります。
コメントを用いて章立てをするのが一般的ですが、機能ごとにfunction()にまとめていくことでコード自体で章立てを表現することができます。
#1. Copyright statement -----
# © 2024 Author: Name.
# All rights reserved.
#2. Author -----
# Author: Name.
# Date: YYYYMMDD
# Contact: mail
#3. File description -----
# Purpose: XXX
# Inputs: XXX
# Outputs: XXX
#4. source() and library()-----
#5. Function definitions -----
RunAll <- function(){
df <- Read()
df <- Clean(df)
Analyze(df)
}
Read <- function(){
}
Clean <- function(){
}
Analyze <- function(){
}
#6. Executed statements -----
RunAll()
おまじないとして、下記のコードを使って設定を初期化してから解析するようにしています。各スクリプに入れても良いと思いますが、私は00_prepare.Rという名前で別ファイルにして後から source(“./utils/00_prepare.R”) で呼び出しています。
# language setting
Sys.setenv(LANGUAGE = "en_US.UTF-8")
# clear memory
rm(list = ls())
# clear console
cat("\014")
# clear plots
if (!is.null(dev.list())) dev.off()
枠を守る
RStudioの縦線がなにか気になった方はいませんか? これは80文字の印です。パンチカードの時代や、ディスプレイ幅が現代よりも限られていたときに提案された歴史的背景があるそうです。(大きなディスプレイを使える環境の人はさして気にせず横長のものを書く傾向がある気がします)
厳密に80文字以内で改行しなくても良いと思いますが、やはり横長になりすぎない方が読みやすいのも事実。できれば80文字までに、少なくとも120文字までには改行する、くらいがよいのではないでしょうか。
数学の筆記試験で、解答用紙が大きい場合は縦に割って2カラムにしたほうが読みやすくなるのに似ています
縦の長さも1ファイルは300行程度までにします。それ以上になるときは、順序で分割するか、処理の一部を関数にして別ファイルにするなどした方が読みやすくなります。
パイプ演算子 (%>%) を繰り返すのは5−7回程度までにします。それ以上長くなるときには中間変数を置きましょう。
関係詞や接続詞を繰り返すと文章が分かりづらくなるので適宜分割しましょう、というのと似ています
スペースの使い方、カッコ前後の改行の使い方などにもルールをつくります。Tidyverse style guidelineを参考にします。すべてを常に実行できるわけではありません。適宜{styler}パッケージを使って自動で整えましょう。RStudioのAddinsから使うのが便利です。
{tidyverse}を優先する
Rのサンプルコードを探すと、同じことをするのにいろいろな方法が出てきて混乱しませんか? Rがオープンソースで開発されてきたのが一因です。パッケージの読み込み方も、エクセルファイルの読み込み方も、いろいろな方法が提案されています。微妙な差異はあるものの、どれかが使えたら十分です。
{tidyverse}という一連のパッケージ群が便利なので、それを優先するのがよいと思います。
どれでも使えたらよいのでしょうが、混在するとわけがわからなくなります。何を優先するかを決めておきましょう
参考資料
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック
統計推論再考 – 概念と技法 – (特にI-2プログラミングの姿勢と技術、VIプログラミング実践)
名古屋市立大学医学部卒業後、南生協病院での初期研修を経て、東京大学医学部附属病院精神神経科、東京武蔵野病院で専攻研修。日本専門医機構認定精神科専門医、精神保健指定医。臨床と並行してメタアナリシスを中心とした臨床研究を主導。筆頭著者として、JAMA Psychiatry, British Journal of Psychiatry, Schizophrenia Bulletin, Psychiatry and Clinical Neuroscienceなどのトップジャーナルに論文を発表。不眠の認知行動療法 (CBT-I) などの心理療法や、精神科疾患の薬物療法について、臨床で抱いた疑問に取り組んでいる。メディア報道・講演など。
免責事項:当ウェブサイトは所属団体の意見を代表するものではありません。管理人は、細心の注意を払って当ウェブサイトに情報を作成していますが、情報の正確性および完全性を保証するものではありません。当ウェブサイトの情報もしくはリンク先の情報を利用したことで直接・間接的に生じた損失に関し、管理人は一切責任を負いません。