2016-01-28 2 views
5

他の列名で列があります。私は各列名の値を取得したい。文字列を使用してdplyr(または基数R)の1行あたりの列を選択します

# three columns with values and one "key" column 
library(dplyr) 
data = data.frame(
    x = runif(10), 
    y = runif(10), 
    z = runif(10), 
    key = sample(c('x', 'y', 'z'), 10, replace=TRUE) 
) 

# now get the value named in 'key' 
data = data %>% mutate(value = VALUE_AT_COLUMN(key)) 

私は答えはのmutateの怠惰なevalのバージョンとは何かを持っているかなり確信しているが、私は私の人生のためにそれを把握することはできません。

ご協力いただければ幸いです。

+1

また、 'data [c(" x "、" y "、" z ")] [cbind(seq_len(nrow(data))、match(data $ key、names(data))) ] 'を使用して、すべての行でグループ化することを避けます(中間変換のコストはおそらく低くなります)。 –

+0

@alexis_laz私は、すべての列を列挙する必要がない、より拡張性のあるアプローチを希望します。 – sharoz

+1

列の順序に応じて、プログラム的に必要な列を抽出する方法はたくさんあるはずです。 'data [1:3]'、 'data [unique(data $ key)]'、 'data [%names]'、 'data'など –

答えて

5

は基本Rソリューションです:メモリ効率的かつ迅速な解決のために

data$value = diag(as.matrix(data[,data$key])) 
+1

面白いですが、これはメモリが効率的ではないと思います。 –

+2

もっとメモリ効率の良いベースメソッドがあるかもしれませんが、パフォーマンスのために行くなら、 'data.table'か' dplyr'を探してください。より多くのパッケージをロードしたくない場合、データが大量ではない場合、これは機能します。 –

6

data.tableを試すことができます。 'data.frame'を 'data.table'(setDT(data))に変換し、行の列でグループ化し、.SDを使用して 'key'で指定された列をサブセット化します。

library(data.table) 
setDT(data)[, .SD[, key[[1L]], with=FALSE] ,1:nrow(data)] 

または別のオプション前の場合のように、行のシーケンスによりグループ化した後(それfactorなど)characterクラスに「鍵」を変換した後getあります。ここで

setDT(data)[, get(as.character(key)), 1:nrow(data)] 

はこれにベースRソリューションがなければならないようですが、間違いなく感じている do

library(dplyr) 
data %>% 
    group_by(rn = row_number()) %>% 
    do(data.frame(., value= .[[.$key]])) 
+0

私は他のライブラリを使ってこれを行うことができますが、もう一つのデータフレームライブラリをインポートする必要を避けようとしています – sharoz

+0

@sharoz 'do'を使用して' dplyr'で可能です – akrun

+2

答えとして投稿できますか? – sharoz

4

と一つの選択肢であるが、私は何ができる最善のは、最初に変換するために、tidyrとありましたデータをワイドフォームに変換し、目的のキーに一致する観測値だけをフィルタリングします。

data %>% 
    add_rownames("index") %>% 
    gather(var, value, -index, -key) %>% 
    filter(key == var) 

ほぼ働く基地R液:

data[cbind(seq_along(data$key), data$key)] 

与えられたデータについては、それが動作を行い、それは、マトリックスを使用しているため、これは、2つの重大な問題を有しています。 1つは、因子の順序が重要であるということです。なぜなら、それを強制的に強制し、列名ではなく因子レベルで列を選択するからです。もう1つは、key列のために、characterが選択されているため、結果の出力はnumericではなくcharacterです。これは、マトリックスへの変換ではcharacterが選択されているためです。重要な問題は、「X」の寸法があるように「i」は同じ数の列を有する行列とすることができる「[」、単一の引数によって配列をインデックス付けするとき

のマトリックスの挙動に何らdata.frameアナログがないことです;結果は 'i'の各行のインデックスのセットに対応する要素を持つベクトルになります。

これらの問題を考えると、私はおそらく列が可変選択可能であるという事実は、彼らはおそらく同じ観察可能な単位で異なる観測を表していることを意味するので、tidyr解決策となるだろう。ここで

5

、あなたは、元のデータを更新する必要があります。次のように結合を実行することにより、テーブル:data$keykey2一致する行について

data[.(key2 = unique(key)), val := get(key2), on=c(key="key2"), by=.EACHI][] 

が算出されます。これらの行は、key2に含まれる列の値で更新されます。たとえば、key2="x"は行1,2,6,8,10と一致します。 data$xの対応する値はdata$x[c(1,2,6,8,10)]です。 by=.EACHIは、key2の各値に対して式get(key2)が確実に実行されます。

この操作は一意の値に対してのみ実行されるため、行単位で実行するよりもかなり高速にする必要があります。また、data.tableは参照によって更新されるため、メモリ効率がよくなければなりません(速度も向上します)。

関連する問題