1. ホーム
  2. r

[解決済み] データフレームの列を$と文字値で動的に選択する

2022-05-30 14:24:53

質問

異なる列名のベクトルがあり、data.frameからその列を抽出するために、それらのそれぞれをループすることができるようにしたいのです。例えば、次のようなデータセットがあるとします。 mtcars というデータセットと、文字ベクトルに格納されたいくつかの変数名 cols . から変数を選択しようとすると mtcars の動的サブセットを使って cols を使用すると、これらのいずれも機能しません。

cols <- c("mpg", "cyl", "am")
col <- cols[1]
col
# [1] "mpg"

mtcars$col
# NULL
mtcars$cols[1]
# NULL

と同じ値を返すようにするにはどうしたらよいでしょうか?

mtcars$mpg

さらに、どのようにすれば cols のすべてのカラムをループして、何らかのループで値を取得することができます。

for(x in seq_along(cols)) {
   value <- mtcars[ order(mtcars$cols[x]), ]
}

どのように解決するのですか?

このようなサブセット化を行うには $ . ソースコードでは ( R/src/main/subset.c ) には、次のように書かれています。

/*$サブセット演算子です。

第一引数だけを評価するようにする必要があります。

2番目は評価ではなく、マッチングが必要なシンボルになります。

*/

第二論?なんですって!?ということに気づかなければなりません。 $ は、R の他のすべてのものと同様に、(たとえば ( , + , ^ など) は関数で、引数を取って評価される。 df$V1 は次のように書き換えることができる。

`$`(df , V1)

あるいは

`$`(df , "V1")

しかし...

`$`(df , paste0("V1") )

...などは決してうまくいきませんし、第2引数で最初に評価されなければならない他のものもうまくいきません。第2引数に渡すことができる文字列は ではありません。 が評価されました。

代わりに [ (または [[ を使うこともできます。)

例えば

var <- "mpg"
#Doesn't work
mtcars$var
#These both work, but note that what they return is different
# the first is a vector, the second is a data.frame
mtcars[[var]]
mtcars[var]

ループを使わずに順序付けを行うこともできます。 do.call への呼び出しを構成するために order . 以下は再現例です。

#  set seed for reproducibility
set.seed(123)
df <- data.frame( col1 = sample(5,10,repl=T) , col2 = sample(5,10,repl=T) , col3 = sample(5,10,repl=T) )

#  We want to sort by 'col3' then by 'col1'
sort_list <- c("col3","col1")

#  Use 'do.call' to call order. Seccond argument in do.call is a list of arguments
#  to pass to the first argument, in this case 'order'.
#  Since  a data.frame is really a list, we just subset the data.frame
#  according to the columns we want to sort in, in that order
df[ do.call( order , df[ , match( sort_list , names(df) ) ]  ) , ]

   col1 col2 col3
10    3    5    1
9     3    2    2
7     3    2    3
8     5    1    3
6     1    5    4
3     3    4    4
2     4    3    4
5     5    1    4
1     2    5    5
4     5    3    5