2011-12-12 8 views
13

にDATAFRAMEしますリストは、私はこのようになります<code>ul</code>と呼ばれる醜いリストに対処する必要がR

[[1]] 
[[1]]$param 
    name  value 
"Section"  "1" 

[[1]]$param 
    name value 
"field"  "1" 

[[1]]$param 
      name   value 
"final answer"   "1" 

[[1]]$param 
    name value 
"points" "-0.0" 


[[2]] 
[[2]]$param 
    name  value 
"Section"  "1" 

[[2]]$param 
    name value 
"field"  "2" 

[[2]]$param 
      name   value 
"final answer"   "1" 

[[2]]$param 
    name value 
"points" "1.0" 


[[3]] 
[[3]]$param 
    name  value 
"Section"  "1" 

[[3]]$param 
    name value 
"field"  "3" 

[[3]]$param 
      name   value 
"final answer"  "0.611" 

[[3]]$param 
    name value 
"points" "1.0" 

私は単純なデータフレームにリストを変換したいと思い、すなわち

Section field final answer points 
     1  1    1  -0.0 
     1  2    1  1.0 
     1  3   0.611  1.0 

これを達成するための簡単な方法はありますか?あるいは、各リストに個別にアクセスしてデータフレームにバインドする関数を作成する必要がありますか?

データは醜いxmlファイルからインポートされるため、誰かが再生したい場合はRData fileへのリンクがあります。再現可能なコードがありません。どうもありがとうございました。

答えて

12

おそらくもっと良い解決策がありますが、これはあなたを始められるはずです。まず、いくつかのライブラリを読み込みます。

R> library(plyr) 
R> library(reshape2) 

リストを2つの部分に分けて処理します。

##lapply applies ldply to each list element in turn 
ul1 = lapply(ul, ldply) 

##We then do the same again 
dd = ldply(ul1)[,2:3] 

我々は彼らのリストの順番

R> dd$num = rep(1:3, each=4) 

に応じた出力をラベル付け次その後、我々は

ワイドフォーマットに長いから変換
R> dcast(dd, num ~ name) 

    num field final answer points Section 
1 1  1   1 -0.0  1 
2 2  2   1 1.0  1 
3 3  3  0.611 1.0  1 
9

ulの構造に一貫性があるとして、あなたは、単にすることができます個々の列を個別に取得します(基数Rのみを使用)。

section <- vapply(ul, function(x) as.numeric(x[[1]][2]), 0) 
field <- vapply(ul, function(x) as.numeric(x[[2]][2]), 0) 
final_answer <- vapply(ul, function(x) as.numeric(x[[3]][2]), 0) 
points <- vapply(ul, function(x) as.numeric(x[[4]][2]), 0) 

(ここでは、sapplyの代わりにvapplyを使用します。これは、ここで必要なベクトルがより高速で確実に返されるためです)。
そして、あなたは、単にすべて一緒にそれを置くことができます:私はnumericにすべてを変換

> data.frame(section, field, final_answer, points) 
    section field final_answer points 
1  1  1  1.000  0 
2  1  2  1.000  1 
3  1  3  0.611  1 

注意を。すべてを文字として保持したい場合は、を呼び出すたびにas.numericを削除し、0""に交換してください。


後期更新:

完全なデータを抽出し、素敵なoneliner実際にあります:

do.call("rbind", lapply(ul, function(x) as.numeric(vapply(x, "[", i = 2, "")))) 

います:

 [,1] [,2] [,3] [,4] 
[1,] 1 1 1.000 0 
[2,] 1 2 1.000 1 
[3,] 1 3 0.611 1 

colnames使用を得るためには、 :

> vapply(ul[[1]], "[", i = 1, "") 
     param   param   param   param 
    "Section"  "field" "final answer"  "points" 
1

は、私はあなたが「個別リストにアクセスする機能」によって何を意味するかわからないんだけど、これは「lapply」と「do.call( 『rbind』、...)」を使用して非常に簡単です:

あなたを読み込めませんでした。RDataファイルであるため、このコードはリストのために機能します。

ul <- list(param = list(
      c(name = "Section", value = "1"), 
      c(name = "field", value = "1"), 
      c(name = "final answer", value = "1"), 
      c(name = "points", value = "-0.0")), 
      param = list(
      c(name = "Section", value = "1"), 
      c(name = "field", value = "2"), 
      c(name = "final answer", value = "1"), 
      c(name = "points", value = "1.0"))) 

リストが異なる場合は、詳細を調整する必要があります。一般原則は同じままです。コードをきれいに保つために、ul [[1]]、ul [[2]]などのすべての名前や値を取り出す 'extractitem'関数を定義しましょう。この関数は、あなたが必要です。

extractitem <- function(listelement, item) 
    unname(lapply(listelement, function(itemblock) itemblock[item])) 

ここでは、lapplyを使用してul要素を要素単位で処理します。各要素について、値をデータフレームに抽出し、 '名前'に従って列に名前を付けます。

rowlist <- lapply(ul, function(listelement) { 
    d <- data.frame(extractitem(listelement, "value"), stringsAsFactors = FALSE) 
    names(d) <- unlist(extractitem(listelement, "name")) 
    d 
}) 

rowlistは現在データフレームのリストです。 「rbind」を使用してそれらを単一のデータフレームに統合することができます。前のステップで(データやオーバーヘッドの低いものとは対照的に)前のステップでデータフレームを使用することについての素晴らしい点は、必要に応じてrbindが列を並べ替えるということです。フィールドの順序が要素から要素に変わる場合、右。

finaldf <- do.call("rbind", rowlist) 

「文字」の要素をアプリケーションに適したものに変更する必要があります。

finaldf$points <- as.numeric(finaldf$points) 

などとなる。最後のステップは、自動的に生成された行名ストリッピングすることにより、データフレームをクリーンアップ:あなたは物事を微調整する必要がある場合には

rownames(finaldf) <- NULL 

を、一般的な考え方は、各ULをフォーマットする関数を記述することである[[I]]正しい列名を持つデータフレームとして扱います。 lapplyを使ってulの各要素に対してその関数を呼び出します。最後に結果リストをdo.call( "rbind"、...)で折りたたむ。

10

同様の問題への答えは、このリンクでマルク・シュワルツによって与えられた: https://stat.ethz.ch/pipermail/r-help/2006-August/111368.html

私はリンクが削除された場合には、それをコピーしています。

as.data.frame(sapply(a, rbind)) 

    V1 V2 V3 
1 a b c 
2 1 3 5 
3 2 4 6 

か:リンクの

as.data.frame(t(sapply(a, rbind))) 
    V1 V2 V3 
1 a 1 2 
2 b 3 4 
3 c 5 6 
+0

おかげで、私は質問をするとき、私はそれについて知りませんでした。 – Emer

+0

あなたはようこそ! – rafaelvalle

関連する問題