使用 ID 列展平数据框中的列表列

Flatten list column in data frame with ID column

我的数据框包含 select 多问题类型的调查的输出。有些单元格有多个值。

df <- data.frame(a=1:3,b=I(list(1,1:2,1:3)))
df
  a       b
1 1       1
2 2    1, 2
3 3 1, 2, 3

我想展开列表以获得以下输出:

df
  a       b
1 1       1
2 2       1
3 2       2
4 3       1
5 3       2
6 3       3

应该很容易,但不知何故我找不到搜索词。谢谢。

您可以只使用 "tidyr" 中的 unnest:

library(tidyr)
unnest(df, b)
#   a b
# 1 1 1
# 2 2 1
# 3 2 2
# 4 3 1
# 5 3 2
# 6 3 3

使用 base R,一个选项是 stack 在将 'b' 列的 list 元素命名为 'a' 的元素之后。我们可以使用 setNames 来更改名称。

stack(setNames(df$b, df$a))

或者另一种选择是使用 unstack 自动将 'b' 的列表元素命名为 'a' 元素,然后执行 stack 以获得 data.frame输出。

stack(unstack(df, b~a))

或者我们可以使用 splitstackshape 中的便捷函数 listCol_llist 转换为 data.frame

library(splitstackshape)
listCol_l(df, 'b')

这是一种方法,data.table:

require(data.table)
data.table(df)[,as.integer(unlist(b)),by=a]

如果b一致存储,as.integer可以跳过。您可以查看

unique(sapply(df$b,class))
# [1] "numeric" "integer"

这是另一个基本解决方案,远不如迄今为止发布的任何其他解决方案优雅。为了完整起见,尽管我个人会推荐 akrun 的基本解决方案。

with(df, cbind(a = rep(a, sapply(b, length)), b = do.call(c, b)))

这会将第一列构造为 a 的元素,其中每个元素都会重复以匹配 b 中相应列表项的长度。第二列是 b "flattened" using do.call() with c().

正如 Ananda Mahto 在评论中指出的那样,在最新版本的 R(3.2,如果我没记错的话)中,sapply(b, length) 可以替换为 lengths(b)

基础 R 方法也可能是为每一行创建一个新的 data.frame,然后 rbind

df <- data.frame(a=1:3,b=I(list(1,1:2,1:3)))
df

df <- lapply(seq_along(df$a), function(x){data.frame(a = df$a[[x]], b = df$b[[x]])})
df <- do.call("rbind", df)
df