Rで参照した文字列をスクリプトとして実行するやり方

R/Rstudio

Rで分析する際に、リストの中にある変数名を参照して、それを分析で使用する変数として使用してくれる方法はないかな、と調べていたところ、eval関数を使えば、うまくいけたので、まとめます。

eval関数とは

eval関数は、関数内に入れられた文字列(””で囲まれたもの)をRのスクリプトとして実行することができる関数です。
tidyverse()を読み込んだ時に使用できる irisのデータを使って例を示すと以下のように使うこともできます。

library(tidyverse) 
eval(parse(text= paste0("iris$","Sepal.Length"))) #evalを使って、iris$Sepal.Lengthを表現

出力結果は以下のようになります。
irisのSepal.lengthの中身を表現できました。

> eval(parse(text= paste0("iris$","Sepal.Length")))
  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1 5.4 5.1 4.6 5.1 4.8 5.0 5.0 5.2 5.2 4.7 4.8 5.4 5.2
 [34] 5.5 4.9 5.0 5.5 4.9 4.4 5.1 5.0 4.5 4.4 5.0 5.1 4.8 5.1 4.6 5.3 5.0 7.0 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 5.0 5.9 6.0 6.1 5.6 6.7
 [67] 5.6 5.8 6.2 5.6 5.9 6.1 6.3 6.1 6.4 6.6 6.8 6.7 6.0 5.7 5.5 5.5 5.8 6.0 5.4 6.0 6.7 6.3 5.6 5.5 5.5 6.1 5.8 5.0 5.6 5.7 5.7 6.2 5.1
[100] 5.7 6.3 5.8 7.1 6.3 6.5 7.6 4.9 7.3 6.7 7.2 6.5 6.4 6.8 5.7 5.8 6.4 6.5 7.7 7.7 6.0 6.9 5.6 7.7 6.3 6.7 7.2 6.2 6.1 6.4 7.2 7.4 7.9
[133] 6.4 6.3 6.1 7.7 6.3 6.4 6.0 6.9 6.7 6.9 5.8 6.8 6.7 6.7 6.3 6.5 6.2 5.9

見てわかるように、このスクリプトは、iris$Sepal.lengthと同じ意味なので、eval()を使う必要はありませんが、このように、””で囲まれた文字列を、スクリプトとして実行していることがわかります。

ちなみに、text=paste0 というのは、カンマ(,)で区切られた文字をくっつける際に、空白なしで結合させるという意味です。
paste0()ではなく、paste()とすると、結合する文字列の間にスペースができてしまいます。

> parse(text= paste0("iris$","Sepal.Length")) #結合する文字列はくっついている
expression(iris$Sepal.Length)
> parse(text= paste("iris$","Sepal.Length")) #結合する文字列の間にスペースが入っている。
expression(iris$ Sepal.Length)

「Rで参照した文字列をスクリプトとして実行する」使い道

ものすごく使いどころは限られてくるかもですが、例えば、相関分析をする際に、「リストをあらかじめ作って、そのリストを通して分析の変数を指定したい」というニッチなわがままをevalで実現できます。

例えば、irisには、”Sepal.Length” 、”Sepal.Width”、 “Petal.Length”、 “Petal.Width” 、”Species”の5列がありますが、Sepal(がく)と、Petal(花びら)を分けて、Sepalの長さとPetalの長さと幅の関係、Sepalの幅と Petalの長さと幅の関係 だけを分析したいとすれば、以下のようにリストを複数に分けて、そのリストの要素を、eva関数に渡してあげれば、文字列として指定するリストから相関分析をすることができます。

list1<-names(iris)[1:2] #Sepalの列名リスト
list2<-names(iris)[3:4] #Petalの列名リスト
cor.test(eval(parse(text= paste0("iris$",list1[1]))), 
         eval(parse(text= paste0("iris$",list2[1])))) #Sepal.LengthとPetal.Lengthの相関

	Pearson's product-moment correlation

data:  eval(parse(text = paste0("iris$", list1[1]))) and eval(parse(text = paste0("iris$", list2[1])))
t = 21.646, df = 148, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.8270363 0.9055080
sample estimates:
      cor 
0.8717538

上記の list1[1] は、” Sepal.Length “、list2[1]は” Petal.Length “です。
念のため、evalを使わないで、ちゃんと変数名を指定して相関分析をしたものは以下です。

> cor.test(iris$Sepal.Length,iris$Petal.Length)

	Pearson's product-moment correlation

data:  iris$Sepal.Length and iris$Petal.Length
t = 21.646, df = 148, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.8270363 0.9055080
sample estimates:
      cor 
0.8717538

結果が一致しているのであっていますね。

eval()をつかえば、文字列をスクリプト文として実行してくれるようになります。
そのため、list1[2]と打てば、Sepal.Widthの分析もできるので、例えば、list1とlist2に分析したい変数の組み合わせをそれぞれ用意して、for文でlistのそれぞれの番号をインクリメントさせれば、リストに格納された変数間の組み合わせの分析を自動で行うということもできそうです。

まとめ

Rで参照した文字列をスクリプトとして実行するやり方は、eval()を使うとうまくできる。
データセットを指定する○○$の部分と都度変わるlist[n]の部分を組み合わせるときはpaste0()を使うことで、「データセットの特定の列」ということをうまく指定できる。

このあたりをうまく応用すれば、 Rで参照した文字列をスクリプトとして実行できそうです。

タイトルとURLをコピーしました