2016-05-10 46 views
1

我想將列表的列表轉換爲data.frame。首先,我的每個子列表只有長度爲1,因此我使用stack(as.data.frame(...)),但堆棧沒有縫合才能生成多列data.frame。那麼,什麼是最好的方式來實現這一目標:如何使用堆棧產生多列數據框?

# works fine with only sublists of length 1 
l = list(a = sample(1:5, 5), b = sample(1:5, 5)) 
> stack(as.data.frame(l)) 
    values ind 
1  5 a 
2  4 a 
3  1 a 
4  2 a 
5  3 a 
6  2 b 
7  1 b 
8  3 b 
9  5 b 
10  4 b 

現在我的列表是一個列表的列表:

l = list(a = list(first = sample(1:5, 5), sec = sample(1:5, 5)), b = list(first = sample(1:5, 5), sec = sample(1:5, 5))) 
stack(as.data.frame(l)) 
    values  ind 
1  4 a.first 
2  5 a.first 
3  3 a.first 
4  1 a.first 
5  2 a.first 
6  3 a.sec 
7  5 a.sec 
8  1 a.sec 
9  2 a.sec 
10  4 a.sec 
11  5 b.first 
12  4 b.first 
13  3 b.first 
14  1 b.first 
15  2 b.first 
16  3 b.sec 
17  4 b.sec 
18  1 b.sec 
19  2 b.sec 
20  5 b.sec 

,而我想還是有一列indab和兩個

+0

什麼是預期的輸出? – Sotos

回答

2

我們可以通過連接(c)拼合listfirstsec嵌套元素(「L1」),請從子串'l1'('nm1'和'nm2')的,split'l1'乘以'nm1'(即,通過去除前綴獲得的子串),而我們將'l1'的names設置爲'nm2'(通過去除以.開始的後綴獲得的子串),循環通過liststack它('lst')。然後,我們cbind'ind'列(它在所有list元素中都是相同的,所以我們從第一個列表元素 - lst[[1]][2]中得到)與'值'列即第一列。

l1 <- do.call(c, l) 
nm1 <- sub("[^.]+\\.", "", names(l1)) 
nm2 <- sub("\\..*", "", names(l1)) 
lst <- lapply(split(setNames(l1, nm2), nm1), stack) 
cbind(lst[[1]][2],lapply(lst, `[[`, 1)) 
# ind first sec 
#1 a  1 1 
#2 a  5 5 
#3 a  4 4 
#4 a  3 3 
#5 a  2 2 
#6 b  3 4 
#7 b  4 5 
#8 b  2 2 
#9 b  1 3 
#10 b  5 1 

或者使用dplyr/purrr我們可以得到預期的輸出。

library(purrr) 
library(dplyr) 
l1 <- transpose(l) 
n1 <- names(l1) 
l1 %>% 
    map(stack) %>% 
    bind_cols %>% 
    setNames(., make.unique(names(.))) %>% 
    select(ind, matches("value")) %>% 
    setNames(., c("ind", n1)) 
#  ind first sec 
# (fctr) (int) (int) 
#1  a  1  1 
#2  a  5  5 
#3  a  4  4 
#4  a  3  3 
#5  a  2  2 
#6  b  3  4 
#7  b  4  5 
#8  b  2  2 
#9  b  1  3 
#10  b  5  1 
+0

確定刪除評論,即使每個子列表都有兩個以上的條目(這裏是第一個和第二個條目),也是可行的。謝謝 – clemlaflemme

+0

@clemlaflemme感謝您的更新。我添加了一個更靈活的方法 – akrun

1

這裏是另一種方法:

df <- stack(as.data.frame(l)) 
# split names of variables 
indVars <- strsplit(as.character(df$ind), split="\\.") 
# add variables to data.frame 
df$letters <- sapply(indVars, function(i) i[1]) 
df$order <- sapply(indVars, function(i) i[2]) 

# get final data.frame 
cbind("order"=unstack(df, letters~order)[,1], unstack(df, values~order)) 
相關問題