簡體   English   中英

R中數據框的列表列表

[英]List of lists to dataframe in R

我必須處理一個名為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

有沒有簡單的方法可以實現這一目標? 還是我必須讓一個函數單獨訪問每個列表並將其綁定到數據框?

數據是從較丑陋的xml文件中導入的,因此,如果有人想玩它,可以找到RData文件的鏈接。 抱歉,沒有可復制的代碼。 非常感謝你。

可能有更好的解決方案,但這應該可以幫助您入門。 首先,我們加載一些庫

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

馬克·施瓦茨(Marc 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

由於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)

(請注意,我使用vapply而不是sapply因為它更快並且可靠地返回了向量,這在這里是必需的)。
然后,您可以將所有內容放在一起:

> 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並在每次對vapply調用vapply 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" 

我不確定“一個函數分別訪問每個列表”是什么意思,但是使用“ 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 <- 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
})

現在,行列表是數據幀的列表; 我們可以使用“ rbind”將它們合並為一個數據框。 在上一步中使用數據幀的好處(相對於矢量或開銷較低的東西)是rbind會在必要時對列進行重新排序,因此,如果字段的順序在元素之間變化,那么我們仍然對。

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

我們仍然需要通過以下方式將finaldf的元素從“字符”更改為適合您的應用程序的任何元素:

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

等等。 最后一步是通過剝離自動生成的行名稱來清理數據框:

rownames(finaldf) <- NULL

萬一您需要進行調整,通常的想法是編寫一個函數,該函數會將每個ul [[i]]格式化為具有正確列名的數據幀。 然后使用lapply在ul的每個元素上調用該函數; 最后使用do.call(“ rbind”,...)折疊結果列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM