0

キュレーターがリレーショナル データベースと 1 対多の関係を認識していない Excel スプレッドシートからいくつかのデータを読み込んだので、複数の変数を 1 つの列に入れました。

>df <- data.frame(id=c("X1", "X23", "X5"), vars=c("foo, bar, hello", "world", NA), var2=c(1,2,3))
>df
   id            vars var2
1  X1 foo, bar, hello    1
2 X23           world    2
3  X5            <NA>    3

列を新しいデータ フレームに変換しvarsて、1 対多の関係を持つことができるようにします。

>df
     id var2
X1   X1    1
X23 X23    2
X5   X5    3

>df2
   id   var
1  X1   foo
2  X1   bar
3  X1 hello
4 X23 world

vars各エントリが変数のベクトルであるリストに列を解析できます。

>library(stringr)
>halfway <- str_split(df$vars, pattern=", ")
>halfway
[[1]]
[1] "foo"   "bar"   "hello"

[[2]]
[1] "world"

[[3]]
[1] NA

しかし、このリストを取得して long に変換する方法がわかりませんdata.frame

いろいろ試してみましたが、各変数が属する ID に関する情報を失うことなく長い形式にすることはできません ( を使用unlist)。私も見ましreshapeたが、私が望むことをしていないようです。

for ループを使用して新しいテーブルを繰り返し作成することもできますが、それは非常に非効率的です。これに対するエレガントな解決策はありますか?

4

3 に答える 3

2

data.tableこれは、パッケージを使用して非常に簡単な方法で実行できます。

library(data.table)
dt = as.data.table(df)
df2 = dt[, list(var=str_split(vars, ", ")[[1]]), by=id]
df2 = df2[!is.na(var), ]

これの利点の 1 つは、複数の ID 列 (id、id2、id3 など) がある場合、それを次のように変更できることです。

df2 = dt[, list(var=strsplit(vars, ", ")[[1]]), by=c("id", "id2", "id3")]
于 2013-08-01T01:54:47.930 に答える
2

concat.split.multiple私の「splitstackshape」パッケージには、分割を実行して 1 つのステップで再形成を行うオプションがあり、NA値を含む行を削除するだけです。

library(splitstackshape)
out <- concat.split.multiple(df, "vars", ",", direction = "long")
out[complete.cases(out), ]
#    id var2 time  vars
# 1  X1    1    1   foo
# 2 X23    2    1 world
# 4  X1    1    2   bar
# 7  X1    1    3 hello

のシナリオでは、関数の「根性」は速度に関して非常にうまく機能しています。ただし、この特定の機能をベンチマークしたことはありません (ほとんどの場合、最初から非常に大きなデータセットを実際に扱ったことがないためです)。

于 2013-08-01T04:40:30.297 に答える
1

このexpand.grid関数は、データの再形成に役立つことがよくあります。例えば:

> expand.grid(df[1,1],halfway[[1]])
  Var1  Var2
1   X1   foo
2   X1   bar
3   X1 hello

applyデータフレームの各行に対してこれを行うために使用できます:

threequarterway <- lapply(seq(nrow(df)),function(i) expand.grid(df[i,1],halfway[[i]]))

do.call結果のリスト要素を単一のデータ フレームにバインドするには:

df2 <- do.call(rbind,threequarterway)

最後に、David Robinson の回答のように NA 行を削除します。

df2 = df2[!is.na(df2[,2]),]

(私がこれを入力している間に David の回答が表示されました。おそらくもっと良い方法ですが、とにかく知りたいと思うかもしれませexpand.gridん。)

于 2013-08-01T02:23:27.453 に答える