2011-12-12 22 views
13

में dataframe को मैं ul कहा जाता है एक बदसूरत सूची है कि इस तरह दिखता है के साथ सामना करने के लिए है:सूचियों की सूची आर

[[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 

क्या हासिल करने के लिए कोई सीधा तरीका है? या क्या मुझे प्रत्येक सूची को व्यक्तिगत रूप से एक्सेस करने और डेटाफ्रेम पर बाध्य करने के लिए एक फ़ंक्शन बनाना है?

डेटा को एक यूगलियर एक्सएमएल फ़ाइल से आयात किया जाता है, इसलिए यदि कोई इसके साथ खेलना चाहता है तो RData file का लिंक है। पुनरुत्पादित कोड नहीं होने के लिए खेद है। आपका बहुत बहुत धन्यवाद।

उत्तर

12

शायद एक बेहतर समाधान है, लेकिन यह आपको शुरू करना चाहिए। सबसे पहले, हम कुछ पुस्तकालयों

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

लोड फिर दो भागों में अपनी सूची संभाल।

##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 की संरचना के रूप में संगत है, तो आप बस कर सकते हैं प्रत्येक कॉलम को अलग-अलग प्राप्त करें (केवल बेस आर का उपयोग करके):

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 का उपयोग करता हूं क्योंकि यह तेज़ और विश्वसनीय रूप से एक वेक्टर लौटाता है, जिसकी आवश्यकता यहां है)।
तो फिर तुम बस यह सब एक साथ रखा जा सकता है:

> 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 

ध्यान दें कि मैं numeric में सब कुछ बदल दिया। यदि आप सबकुछ अक्षरों के रूप में रखना चाहते हैं, तो as.numeric हटाएं औरपर प्रत्येक कॉल में "" के साथ 0 का आदान-प्रदान करें।


देर अद्यतन:

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 उपयोग पाने के लिए

वहाँ वास्तव में एक अच्छा oneliner कि पूरा डेटा निकालता है :

> 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"))) 

आप विवरण tweak करने के लिए यदि अपनी सूची अलग है हो सकता है; सामान्य प्रिंसिपल वही रहेगा। बस कोड को साफ रखने के, की 'extractitem' समारोह है कि उल [[1]], उल [[2]] एक छोटे से अधिक सामान्य, आदि इस समारोह है के लिए नाम या सभी मान बाहर निकलने के लिए हो रहा है निर्दिष्ट कर सकते हैं आप की जरूरत है।

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

अब हम तत्व द्वारा उल तत्व के माध्यम से चलने के लिए केवल लापरवाही का उपयोग करेंगे; प्रत्येक तत्व के लिए, हम एक डेटा फ्रेम में मान एक्सट्रैक्ट, फिर 'नाम' के अनुसार स्तंभों का नाम दें।

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

पंक्तिसूची अब डेटा फ्रेम की एक सूची है; हम उन्हें 'rbind' के साथ एक डेटा फ्रेम में समेकित कर सकते हैं। (जैसा कि वैक्टर या कम भूमि के ऊपर के साथ कुछ के खिलाफ) पिछले चरण में डेटा फ़्रेम का उपयोग के बारे में अच्छी बात यह है कि rbind यदि आवश्यक स्तंभों को पुन: व्यवस्थित होगा है, इसलिए यदि तत्व को तत्व से क्षेत्रों का क्रम बदल गया है, हम अभी भी सभी कर रहे हैं सही।

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

हम अभी भी finaldf लिए तत्वों "चरित्र" से के माध्यम से, उदाहरण के लिए बदलने के लिए जो कुछ भी करने के लिए अपने आवेदन के लिए उपयुक्त है की जरूरत है

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

और इसी तरह। अंतिम चरण स्वचालित रूप से बना पंक्ति के नाम अलग करना द्वारा डेटा फ्रेम को साफ:

rownames(finaldf) <- NULL 

मामले में आप चीजों को बदलाव करने की जरूरत है, सामान्य विचार एक समारोह है कि प्रत्येक उल स्वरूपित होगा लिखना है [[मैं]] सही कॉलम नामों के साथ डेटा फ्रेम के रूप में; फिर उस कार्य को उल के प्रत्येक तत्व पर लापरवाही से बुलाओ; और अंत में परिणामस्वरूप सूची को do.call ("rbind", ...) के साथ पतन करें।

10

एक ऐसी ही समस्या का उत्तर इस लिंक पर मार्क Schwartz द्वारा दिया गया था: 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

संबंधित मुद्दे