大規模なRプログラムを編成する方法は?


161

複雑なRプロジェクトを実行すると、スクリプトがすぐに長く混乱します。

私のコードを常に操作できるようにするために採用できるいくつかのプラクティスは何ですか?私は次のようなことを考えています

  • ソースファイル内の関数の配置
  • 何かを別のソースファイルに分割するタイミング
  • マスターファイルの内容
  • 機能を組織単位として使用する(Rがグローバル状態へのアクセスを困難にするため、これが価値があるかどうか)
  • インデント/改行の練習。
    • 扱います({?
    • )}のようなものを1行または2行に配置しますか?

基本的に、大きなRスクリプトを整理するための経験則は何ですか?


11
コミュニティのwikiである必要があります
SilentGhost 2009

また、ProjectTemplateパッケージを確認することもできます。
ctbrown 2014

回答:


71

標準的な答えは、パッケージを使用することです。R拡張機能記述を参照してください。マニュアルおよびWeb上のさまざまなチュートリアルを。

それはあなたに与える

  • トピックごとにコードを整理する準自動的な方法
  • ヘルプファイルを作成して、インターフェースについて考えさせることを強くお勧めします
  • 多くの健全性チェック R CMD check
  • 回帰テストを追加する機会
  • 名前空間の手段も同様です。

source()コードを実行するだけで、非常に短いスニペットが機能します。他のものはすべてパッケージに含める必要があります。内部リポジトリ用の内部パッケージを作成できるため、パッケージを公開する予定がない場合でも同様です。

「編集方法」の部分については、R Internalsマニュアルのセクション6に優れたRコーディング標準があります。それ以外の場合は、EmacsのESSモードでデフォルトを使用する傾向があります

2008年8月13日更新: David SmithがGoogle Rスタイルガイドについてブログに投稿しました。


8
ソースツリー/分析を「有機的に」成長させている場合、これを行うのは難しい/面倒ではありませんか?コードに誤りがあることに気付いた場合(新しい問題の領域を探索しているときによくあることです)、(i)ソースを修正する必要があります。(ii)パッケージを再インストールします。(iii)ワークスペースに再読み込みしますか?すでにロードされているパッケージを再ロードするために、library(...)を呼び出す方法はありますか(上記のステップiii)?それが正しいかどうかを確認するために、ワークスペースを強制終了してRを再起動し、ライブラリ/パッケージをリロードする必要はありませんか?
スティーブリアノグルー2009

1
Rコーディングスタイルをグーグルで試します。
ハドリー2009

3
@SteveLianoglouこれはかなり古いことを知っていますが、Hadleyのdevtoolsパッケージを使用すると、すべてのコードを非常に簡単に再読み込みできます。
Dason

1
このブログの投稿は、骨組みの
panterasBox


51

自分のファイルにさまざまな機能を追加するのが好きです。

しかし、Rのパッケージシステムは好きではありません。使いにくいです。

私は、ファイルの機能を環境(他のすべての言語が「名前空間」と呼ぶもの)内に配置してアタッチするために、軽量の代替手段を好みます。たとえば、次のような関数の「util」グループを作成しました。

util = new.env()

util$bgrep = function [...]

util$timeit = function [...]

while("util" %in% search())
  detach("util")
attach(util)

これはすべてutil.Rファイルにあります。ソースを取得すると、環境「util」が取得されるので、呼び出しutil$bgrep()などを行うことができます。しかし、さらに、attach()呼び出しはそれをとても正しくしbgrep()、そのようなことは直接働きます。これらの関数をすべて独自の環境に配置しなかった場合、インタプリタのトップレベルのネームスペース(ls()ます。

すべてのファイルがモジュールであるPythonのシステムをシミュレートしようとしていました。それがある方が良いでしょうが、これは問題ないようです。


ありがとう、ブレンダン。とても便利です。whileループはどうなっていますか?(!(%検索における% "UTIL"()))(UTIL)を取り付けた場合の何が問題になっている
ダン・ゴールドスタイン

2
そのため、調整する場合は、source( "util.R")を何度でも実行できます。
ブレンダンOConnor 2009

whileループは本当に必要ありません-detach(util)が必要なすべてです。それがまだロードされていない場合、エラーが発生するかどうかは思い出せませんが、これは最も安全で機能します。提案を歓迎します。
ブレンダンOConnor 2009

1
機能固有の環境を作成してそれをアタッチするのが私にとっての道です。同じことを別の方法で(モジュール性を高めて)達成する別の方法は、次のものを使用することsys.sourceですMyEnv <- attach(NULL, name=s_env); sys.source(file, MyEnv)。起動時に(sys.source2同じ環境で!)同じ名前の環境が既に存在するかどうかを調べ、新しい環境を作成する代わりにこの環境に供給する関数を宣言することすらします。個人的な機能をすばやく簡単に追加して整理できます:-)
AntoineLizée2013

5
今日これを見ただけで、パッケージの代替に適用されます:github.com/klmr/modules
ctbrown

34

これはプログラマーの場合は特に明白に聞こえるかもしれませんが、コードの論理単位と物理単位について私がどのように考えるかをここに示します。

これがあなたのケースであるかどうかはわかりませんが、Rで作業しているとき、大規模で複雑なプログラムを念頭に置いて開始することはほとんどありません。私は通常、1つのスクリプトで開始し、コードを論理的に分離可能なユニットに分割します。多くの場合、関数を使用します。データ操作および視覚化コードは、独自の関数などに配置されます。また、そのような関数は、ファイルの1つのセクションにグループ化されます(上部にデータ操作、次に視覚化など)。最終的には、スクリプトの保守を容易にし、不良率を下げる方法を考えます。

関数をどのように細かく/粗くするかはさまざまであり、さまざまな経験則があります。たとえば、15行のコード、または「関数はその名前で識別される1つのタスクを実行する必要がある」などです。マイレージはさまざまです。 。Rは参照による呼び出しをサポートしていないため、データフレームや同様の構造体の受け渡しを伴う場合、通常、関数を細かくしすぎています。しかし、これは私が最初にRを使い始めたときのいくつかのばかげたパフォーマンスの誤りに対する過剰補償であるかもしれません。

論理ユニットを独自の物理ユニット(ソースファイルやパッケージのようなより大きなグループなど)に抽出するのはいつですか?私には2つのケースがあります。まず、ファイルが大きくなりすぎて、論理的に関連のないユニット間をスクロールするのが煩わしい場合です。次に、他のプログラムで再利用できる関数がある場合。私は通常、データ操作関数などのグループ化されたユニットを別のファイルに配置することから始めます。その後、他のスクリプトからこのファイルを入手できます。

関数をデプロイする場合は、パッケージについて考え始める必要があります。さまざまな理由で、Rコードを本番環境にデプロイしたり、他の人が再利用したりしていません(簡単に言うと、組織の文化は他の言語を好む、パフォーマンス、GPLに関する懸念など)。また、私は常にソースファイルのコレクションを調整して追加する傾向があり、変更を加えるときは、パッケージを処理したくありません。したがって、このフロントの詳細については、Dirkのような他のパッケージ関連の回答を確認する必要があります。

最後に、あなたの質問は必ずしもRに固有のものではないと思います。このような問題やコーディングプラクティス全般について多くの知恵が含まれているSteve McConnellのCode Completeを読むことをお勧めします。


3
非常に役立つコメント、ars、ありがとう。私はプログラマーですが、他の人とチェックインするのは良いことです。「Rは参照渡しをサポートしていないので、通常、関数の粒度を細かくすることに警戒しています」と言われると、私はReadData()のような関数を書くことに慣れています。CleanData(); AnalyzeData(); GraphData(); そしてRはそれを面倒にします。他の言語で関数を使用する方法と同じように「ソース」を使用する必要があるという考えに目覚めています。
Dan Goldstein、

2
あなたは正しい、ダン。データソースの準備タスクに「ソース」をそのまま使用しているので、実際の分析が行われる他のスクリプトで準備されたdata.frameを使用できます。これは他の言語と比べて奇妙に感じられるだけなので、これが良い習慣であるかどうか確信が持てませんでした。ノートを比較するのは良いことです。:)
ARS

いい答えとコメント。これはRでは特に厄介です。なぜなら、特定の形式のデータを扱うことが多いため、再利用可能な関数を書くのが本当に難しいからです。それで、再利用されることはないとわかっていても、素晴らしい関数コードを書いていますか?それとも、大きなオブジェクトで少し余分な効率を得るためだけに迅速で厄介な手続きコードを書いていますか?ちょっとしたジレンマ.. Rは参照
渡し

まあ、それはできるのですが、効率の向上はありません...
naught101

19

ダークのアドバイスに同意します!私見、単純なスクリプトから文書化されたパッケージにプログラムを編成することは、Rでのプログラミングでは、WordからTeX / LaTeXに切り替えて作成するようなものです。非常に役立つRパッケージの作成: Friedrich Leischによるチュートリアルをご覧になることをお勧めします。


6
パッケージは説得力があります。しかし、彼らはやり過ぎかもしれないと心配しました。私は汎用コードを書いていません。私がしていることのほとんどは、この仮説をテストし、その仮説をテストし、これをプロットし、プロットパラメーターを調整し、それをプロットし、データを再形成し、それをプロットすることです。私は、いったん終了すると、おそらく再実行されないようなことをしています。
Dan Goldstein、

1
その場合、Sweaveを確認する必要があります。RコードとLaTeXを組み合わせたものです。したがって、分析とレポートソースを一緒に利用できます。
ティエリー

15

私の簡潔な答え:

  1. 関数を注意深く書き、一般的に十分な出力と入力を特定します。
  2. グローバル変数の使用を制限します。
  3. S3オブジェクトと、必要に応じてS4オブジェクトを使用します。
  4. 特に関数がC / Fortranを呼び出す場合は、関数をパッケージに入れます。

Rは本番環境でますます使用されるようになっているので、再利用可能なコードの必要性は以前よりも大きくなっています。通訳は以前よりもはるかに堅牢だと思います。RがCよりも100〜300倍遅いことは間違いありませんが、通常、ボトルネックは数行のコードに集中しており、C / C ++に委任できます。データ操作と統計分析におけるRの長所を別の言語に委任するのは間違いだと思います。これらの例では、パフォーマンスのペナルティは低く、いずれにしても、開発作業を節約する価値があります。実行時間だけが問題である場合、私たちはすべてアセンブラーを書くことになります。


11

私はパッケージの書き方を理解するつもりですが、時間を費やしていません。ミニプロジェクトごとに、すべての低レベル関数を「functions /」と呼ばれるフォルダーに保存し、明示的に作成した個別の名前空間にそれらを供給します。

次のコード行は、「myfuncs」という名前の環境が存在しない場合は(attachを使用して)検索パス上に作成し、「functions /」ディレクトリ内の.rファイルに含まれている関数をその環境に取り込みます(使用して) sys.source)。私は通常、これらの行を、高レベルの関数(低レベルの関数を呼び出す)の呼び出し元となる「ユーザーインターフェイス」用のメインスクリプトの先頭に配置します。

if( length(grep("^myfuncs$",search()))==0 )
  attach("myfuncs",pos=2)
for( f in list.files("functions","\\.r$",full=TRUE) )
  sys.source(f,pos.to.env(grep("^myfuncs$",search())))

変更を加えるときは、常に同じ行で再ソースするか、次のようなものを使用できます

evalq(f <- function(x) x * 2, pos.to.env(grep("^myfuncs$",search())))

作成した環境での追加/変更を評価します。

それは私が知っているだらけですが、それについてあまりに形式的になる必要がないようにします(ただし、機会があれば、パッケージシステムを奨励します。うまくいけば、将来そのように移行します)。

コーディング規約に関しては、これは美学に関して私が見た唯一のものです(私はそれらを好きで、大まかにフォローしていますが、Rであまり多くの中括弧を使用していません)。

http://www1.maths.lth.se/help/R/RCC/

[、drop = FALSE]と<-の使用に関する他の「規約」があり、useRのさまざまなプレゼンテーション(通常はキーノート)で提案されている代入演算子として!会議ですが、これらは厳密ではないと思います([、drop = FALSE]は、期待する入力がわからないプログラムに役立ちます)。


6

私をパッケージを支持する別の人として数えてください。必要な場合(リリースされるまで)は、manページとビネットの記述がかなり下手であることを認めますが、ソースdoeをバンドルするための本当に便利な方法になります。さらに、コードの保守に真剣に取り組む場合、Dirkが提起するポイントはすべてplyaに入ります。


4

私も同意します。開始するには、package.skeleton()関数を使用します。コードが二度と実行されないと思われる場合でも、後で時間を節約できるより一般的なコードを作成する動機付けになるでしょう。

グローバル環境へのアクセスに関しては、推奨されませんが、<<-演算子を使用すると簡単です。


3

パッケージの書き方をまだ学んでいないので、私は常にサブスクリプトを調達することで組織してきました。クラスを書くのに似ていますが、それほど複雑ではありません。プログラム的にはエレガントではありませんが、時間をかけて分析を積み重ねてきました。機能する大きなセクションができたら、ワークスペースオブジェクトを使用するため、別のスクリプトに移動してソースするだけです。おそらく、いくつかのソースからデータをインポートし、それらすべてをソートして、交差点を見つける必要があります。そのセクションを追加のスクリプトに追加する場合があります。ただし、「アプリケーション」を他の人に配布したい場合、またはインタラクティブな入力を使用する場合は、パッケージがおそらく適切なルートです。研究者として私はめったに分析コードを配布する必要はありませんが、私はしばしばそれを増強または微調整する必要があります。


私はこの方法を使用しましたが、関数とパッケージはsource( "next_script.R")よりも優れていることに気付きました。私はここでそれについて書いた:stackoverflow.com/questions/25273166/...
アーサー・イップ

1

また、Rの大規模プロジェクトをまとめるための適切なワークフローの聖杯も探していました。私は昨年、このパッケージをrsuiteと呼びました。確かに、私が探していたものでした。このRパッケージは、大規模なRプロジェクトのデプロイメント用に明示的に開発されましたが、小規模、中規模、および大規模のRプロジェクトで使用できることがわかりました。実世界の例へのリンクをすぐに提供します(下記)が、最初に、Rプロジェクトを構築する新しいパラダイムについて説明します。rsuiteます。

注意。私はの作成者でも開発者でもありませんrsuite

  1. 私たちはRStudioですべて間違ったプロジェクトを行ってきました。目標は、プロジェクトやパッケージの作成ではなく、より広い範囲の作成である必要があります。rsuiteでは、可能なすべての組み合わせで、標準のRプロジェクトとRパッケージを保持するスーパープロジェクトまたはマスタープロジェクトを作成します。

  2. Rスーパープロジェクトを使用makeすることで、その下にあるRプロジェクトの下位レベルを管理するためのUnixは不要になります。上部でRスクリプトを使用します。披露させて。rsuiteマスタープロジェクトを作成すると、次のフォルダー構造が得られます。

ここに画像の説明を入力してください

  1. フォルダRは、プロジェクト管理スクリプトを置く場所ですmake

  2. このフォルダーpackagesは、rsuiteスーパープロジェクトを構成するすべてのパッケージを保持するフォルダーです。インターネットからアクセスできないパッケージをコピーして貼り付けることもできます。rsuiteもそれをビルドします。

  3. このフォルダーdeploymentrsuite、パッケージDESCRIPTIONファイルで指定されたすべてのパッケージバイナリを書き込む場所です。したがって、これだけで、完全に再現可能なアクロス時間を予測できます。

  4. rsuiteすべてのオペレーティングシステム用のクライアントが付属しています。私はそれらすべてをテストしました。ただしaddin、RStudioのとしてインストールすることもできます。

  5. rsuiteまたconda、独自のフォルダに独立したインストールを構築することもできますconda。これは環境ではなく、Anacondaからマシンにインストールされた物理的なPythonインストールです。これはRと一緒に機能し、SystemRequirements必要なすべてのPythonパッケージを任意のcondaチャネルからインストールできます。

  6. ローカルリポジトリを作成して、オフラインのときにRパッケージをpullしたり、全体をより速くビルドしたりすることもできます。

  7. 必要に応じて、Rプロジェクトをzipファイルとしてビルドし、同僚と共有することもできます。同僚が同じRバージョンをインストールしていれば、実行されます。

  8. 別のオプションは、Ubuntu、Debian、またはCentOSでプロジェクト全体のコンテナーをビルドすることです。したがって、プロジェクトビルドでzipファイルを共有する代わりに、Dockerコンテナ全体をプロジェクトと共有してすぐに実行できます。

私はrsuite完全な再現性を模索して多くの実験を行っており、グローバル環境にインストールするパッケージに依存しないようにしています。パッケージの更新をインストールするとすぐに、プロジェクト、特に特定のパラメーターを持つ関数への非常に具体的な呼び出しを持つパッケージが機能しなくなることが多いため、これは誤りです。

私が最初に実験を始めたのは、bookdown電子ブックでした。私は、6か月以上の時間のテストを生き残るためのブックダウンを持っているのに十分幸運でした。だから、私がやったことは、元のブックダウンプロジェクトをrsuiteフレームワークに従うように変換することです。これで、プロジェクトには独自のパッケージセットがdeploymentフォルダー内にあるため、グローバルR環境の更新について心配する必要はありません。

次に行ったのは、機械学習プロジェクトを作成することでしたが、そのrsuite方法がわかりませんでした。上部にあるマスター、オーケストレーションプロジェクト、およびマスターの制御下にあるすべてのサブプロジェクトとパッケージ。Rを使用したコーディング方法を実際に変更し、生産性を高めます。

その後、私はと呼ばれる私の新しいパッケージで働き始めましたrTorch。これは、主に次の理由により可能でしたrsuite。それはあなたが考え、大きく行くことができます。

ただし、アドバイスの1つ。学習rsuiteは簡単ではありません。Rプロジェクトを作成する新しい方法を提示するため、難しいと感じます。最初の試みで落胆しないでください、あなたがそれを作るまで坂を登り続けます。オペレーティングシステムとファイルシステムに関する高度な知識が必要です。

メニューからのRStudioように、いつかオーケストレーションプロジェクトを生成できると思いrsuiteます。素晴らしいものになるだろう。

リンク:

RSuite GitHUbリポジトリ

r4dsブックダウン

ケラと光沢のあるチュートリアル

moderndive-book-rsuite

interpretable_ml-rsuite

IntroMachineLearningWithR-rsuite

clark-intro_ml-rsuite

hyndman-bookdown-rsuite

statistics_rethinking-rsuite

fread-benchmarks-rsuite

dataviz-rsuite

小売セグメンテーション-h2o-tutorial

telco-customer-churn-tutorial

sclerotinia_rsuite


-7

Rはインタラクティブな使用や小さなスクリプトには問題ありませんが、大きなプログラムには使用しません。ほとんどのプログラミングで主流の言語を使用し、それをRインターフェースでラップします。


1
そこには非常に大きなパッケージ(つまりプログラム)があります。他の言語で書き直すべきだと真剣に提案していますか?なぜ???
Eduardo Leoni

4
1つの考慮事項は効率です。私はよくRコードをC ++コードに書き直し、100倍速くしました。もう1つはツールのサポートです。Rには、EclipseやVisual StudioのようなIDEに匹敵するものはありません。最後に、プログラムが非常に大きい場合、Rがあまり適さない非統計的タスクを実行している可能性があります。
ジョンD.クック

2
EclipseがRと対話できるようにするプラグイン(Stat-ET)があります。C++はRよりもはるかに高速に動作することに同意します。コードを頻繁に再利用できる場合を除いて、C ++でコードを再コーディングする場合と比較して、高速なコードの利点はそれほど価値がありません。
ティエリー

2
はい、トレードオフがあります(生産性とパフォーマンス)。そして、純粋なデータ分析/統計作業では、Rがしばしば勝つ。しかし、他のタスク(GUI、Webなど)を作成する場合、それが当てはまるかどうかはわかりません。私たちはプロトタイプを作ってRで作業しますが、Python / C ++で製品コードをデプロイします。後者を使用すると、パフォーマンス、さまざまなタスクのための非常に成熟した再利用可能なライブラリ/フレームワークが得られます。しかし、これは流動的な状況であり、Rエコシステムは常に進化しています。
ARS

RcppRプログラムでのC ++コードを含むパッケージの使用は、非常に簡単になります。したがって、Rコードの特定の部分を書き換えることは、Rに非常に簡単に統合できます。さらに、RStudioの登場により、RのIDEが導入されましたが、Visual Studioほど強力ではないかもしれません。
Paul Hiemstra、2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.