如何使用堆栈生成多列数据帧?

时间:2016-05-10 11:31:44

标签: r dataframe stack

我想将列表列表转换为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以及两列firstsec

2 个答案:

答案 0 :(得分:2)

我们可以通过连接(list)嵌套元素('l1')来展平c,从'{1}}获取'l1'('nm1'和''的子串nm2'),names'l1'乘'nm1'(即通过删除前缀得到的子串),同时我们将'{1}}设置为'nm2'(通过删除后缀获得的子串)使用split),循环浏览names.它('lst')。然后,我们list'ind'列(在所有stack元素中都是相同的,因此我们从第一个列表元素 - cbind)获取它,其中包含'value'列,即第一栏。

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

答案 1 :(得分: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))