2013-04-23 7 views
13

私はリストのエントリを含むリストを持っており、構造を転置する必要があります。 元の構造は長方形ですが、サブリストの名前は一致しません。ここでリストのリストを転記する

は一例です:

ax <- data.frame(a=1,x=2) 
ay <- data.frame(a=3,y=4) 
bw <- data.frame(b=5,w=6) 
bz <- data.frame(b=7,z=8) 
before <- list( a=list(x=ax, y=ay), b=list(w=bw, z=bz)) 

私が欲しいもの:

after <- list(w.x=list(a=ax, b=bw), y.z=list(a=ay, b=bz)) 

私は(任意のレベルで)結果のリストの名前を気にしないでください。

明らかにこれは明示的に行うことができます。

after <- list(x.w=list(a=before$a$x, b=before$b$w), y.z=list(a=before$a$y, b=before$b$z)) 

が、これは醜いであり、唯一の2x2の構造のために動作します。これを行う慣習的な方法は何ですか?

+0

あなたが ''適用されます(D、1L、アイデンティティ)と、たとえば、行を収集することによって、データフレーム 'D 'を移調することができます。ですから、データフレームに 'before 'を強制してみてください。それを行うための1つの方法は、tibbleパッケージからの 'tibble :: as_tibble()'であるでしょう。つまり、@alistaireが示唆しているように、 'purrr :: transpose()'を使うと、基底Rの 'apply()'を使うよりも高速です。 (これはC言語で実装されています) – egnha

+0

@egnhaここでは不可能です。リストエントリ自体はデータフレームです。 –

+0

'd < - tibble :: as_tibble(前)'で試してください。 – egnha

答えて

15

次のコードは、before内のすべてのリストのi番目の要素を持つリストを作成します。

lapply(before, "[[", i) 

今、あなたはちょうど

n <- length(before[[1]]) # assuming all lists in before have the same length 
lapply(1:n, function(i) lapply(before, "[[", i)) 

を行う必要があり、それはあなたに何を与える必要がありますあなたは欲しい。それはあまり効率的ではありません(すべてのリストを何度も移動します)、そして現在のリスト要素へのポインタを保持することによって、より効率的になる可能性があります。ここで

+1

私は '1:n'を' seq_along([[1]]の前)に置き換えますが、そうでなければ正常に動作します。リストは必ずしも2x2であるとは限りませんが、大きくはありません(データフレームは大きいです)。 –

+0

ちょうど好奇心から - なぜあなたは 'seq_along'バージョンが好きですか?表現力だけですか? (私はそれがパフォーマンス上、それは同じだと理解しています)。 –

+2

これは、長さが0の場合は間違った結果を返しません。 –

4

は異なるアイデアだ - 'の(実際には、あなたの質問を考えると、多分あなたも、リストのリストを操作する必要はありませんし、ちょうどdata.tableで仕事ができるの年代)data.tabledata.frameを保存することができるという事実を使用します。

library(data.table) 

dt = as.data.table(before) 
after = as.list(data.table(t(dt))) 
+0

これは興味深いアプローチです。私は 'data.table'についていくつか調査しましたが、それを十分に使用していません。 –

+4

これは実際にdata.table 'as.list(data.frame(do.call(rbind、before)))'も必要としません。 – mnel

3

これは古い質問です同じ問題を探している間、私はそれを見つけた、とsecond hit on googleは私の意見でははるかにエレガントな解決策を持っていたものの:

list_of_lists <- list(a=list(x="ax", y="ay"), b=list(w="bw", z="bz")) 
new <- do.call(rbind, list_of_lists) 

newは今あります長方形の構造、奇妙なオブジェクト:次元属性を持つリスト。すべてのサブリストの長さが同じであれば、多くの要素を自由に使用できます。より一般的なR-オブジェクトにそれを変更するためには、例えば、このような行列作成することができます。

new.dims <- dim(new) 
matrix(new,nrow = new.dims[1]) 

new.dimsmatrix()関数は、リストの属性を削除して、保存する必要がありました。もう一つの方法:

new <- do.call(c, new) 
dim(new) <- new.dims 

あなたは今、例えばas.data.frame()でdata.frameに変換して、列に分割または列単位の演算を行うことができます。それを行う前に、必要に応じてマトリックスのdim属性を変更することもできます。

+1

それは欺瞞の結果を与えます。すべての行列要素はリスト –

+0

ですが、それほど類似しているわけではありません。結果は、次元属性を持つ4つの単一文字要素(真行列は原子型のみを含むことができる)のリストです。しかし、ユースケースによっては、これはあまり悪くないだけで、 "真の"マトリックスに変換する必要があります。私はそれを反映するために私のソリューションを編集します。 – zerweck

+0

'rbind'はリストのリストに載っています。 –

1

私はこの問題がありましたが、各要素の名前を保持する解決策が必要でした。私が思いついた解決策は、サブリストがすべて同じ長さでない場合にも機能するはずです。

invertList = function(l){ 
    elemnames = NULL 
    for (i in seq_along(l)){ 
    elemnames = c(elemnames, names(l[[i]])) 
    } 

    elemnames = unique(elemnames) 

    res = list() 
    for (i in seq_along(elemnames)){ 
    res[[elemnames[i]]] = list() 
    for (j in seq_along(l)){ 
     if(exists(elemnames[i], l[[j]], inherits = F)){ 
     res[[i]][[names(l)[j]]] = l[[names(l)[j]]][[elemnames[i]]] 
     } 
    } 
    } 
    res 
} 
3

purrrパッケージは本当に簡単このプロセスを作る:

library(purrr) 

before %>% transpose() 

## $x 
## $x$a 
## a x 
## 1 1 2 
## 
## $x$b 
## b w 
## 1 5 6 
## 
## 
## $y 
## $y$a 
## a y 
## 1 3 4 
## 
## $y$b 
## b z 
## 1 7 8 
関連する問題