京橋のバイオインフォマティシャンの日常

南国のビーチパラソルの下で、Rプログラムを打ってる日常を求めて、、

R言語で『eval + parse + paste関数』を使って、文字列をRプログラムとして実行するTips

f:id:skume:20220115214849p:plain

はじめに

R言語では、文字列をRの命令文として実行することができる。

このプログラム実行のやり方は、 「eval + parse + text + paste」型と表現されることがあるが、 実際には、eval関数、parse関数、paste関数を組み合わせて実行する。

使用する関数群の概要

paste関数は、複数の文字列を連結して一つの文字列にする関数である。 この実装では、sepcollapseの引数オプションとうまく組み合わせる必要がある。

  • sep: 入力文字列を区切るための文字列を指定する。

  • collapse: 出力結果を分離するための任意の文字列を指定する。

parse関数では、R Expressionsをパース(プログラムで扱える形に変換する)する。 ここで、textの引数に、パースするテキスト(文字ベクトル)を指定して、これが実行プログラムとなる。

eval関数では、R Expressionsを評価する。 つまりは、文字列をRのスクリプトとして解釈して実行する。 ここで、R Expressionsとは、数式の意味ではなく、 例えば、parse関数が返すような呼び出しやシンボルなどのリストを意味する。

「eval + parse + text + paste」型の実装例 (1)

次のような、数値を任意の変数に代入する例を考えてほしい。

A <- 1
B <- 2
C <- 3
D <- 4

これを、プログラムで実行してみる。

#前準備
a <- c("A", "B", "C", "D")
b <- 1:4

#プログラム文字列の作成  
p <- paste(a, " <- ", b, sep="", collapse = "; ")
p
#[1] "A <- 1; B <- 2; C <- 3; D <- 4"

#実行
eval(parse(text = p))

#結果の確認
A
#[1] 1
B
#[1] 2
C
#[1] 3
D
#[1] 4

「eval + parse + text + paste」型の実装例 (2)

同様の実行は、assign関数を使って書くこともできる。 assign関数は、環境内の名前に値を割り当てる関数である。

#環境変数を削除
rm(list=ls())

#前準備
a <- c("A", "B", "C", "D")
b <- 1:4

#プログラム文字列の作成  
p <- paste("assign('", a, "', value=", b,")", sep="", collapse = "; ")
p
#[1] "assign('A', value=1); assign('B', value=2); assign('C', value=3); assign('D', value=4)"

#実行
eval(parse(text = p))

#結果の確認
A
#[1] 1
B
#[1] 2
C
#[1] 3
D
#[1] 4

まとめ

「eval + parse + text + paste」型は、 簡単に作成できて、色々なシチュエーションで使えるので、 大変重宝する。

また、「複数の関数の組み合わせ」や「手打ちするには長過ぎるプログラム」の作成などなど、応用範囲も広い。また、実際に使用した実装パターンも取り上げたいと思う。

参考資料

stats.biopapyrus.jp

stat.ethz.ch

www.rdocumentation.org

www.yasuhisay.info

A very useful function: eval parse text&nbsp;pastegoodscienceblog.wordpress.com

nshi.jp