在 data.frame 的列中解包和合并列表

Unpacking and merging lists in a column in data.frame

我有以下 data.frame

id     name   altNames
1001   Joan   character(0)      
1002   Jane   c("Janie", "Janet", "Jan")
1003   John   Jon
1004   Bill   Will
1005   Tom    character(0)      

altNames 可以为空(即字符 (0)),只有一个名称或名称列表。我想要的是 data.frame(或列表),其中来自 name and/or altNames 的每个条目与相应的 id 一起只出现一次,如下所示:

id     name
1001   Joan
1002   Jane
1002   Janie
1002   Janet
1002   Jan
1003   John
1003   Jon
1004   Bill
1004   Will
1005   Tom

最有效的方法是什么?更好的是 dplyr 被利用。 谢谢

编辑:这是数据:

df <- data_frame(
  id = c("1001", "1002","1003", "1004", "1005"), 
  name = c("Joan", "Jane", "John", "Bill", "Tom"), 
  altNames = list(character(0), c("Janie", "Janet", "Jan"), "Jon", "Will", character(0))
)

这是一个可能的data.table方法

library(data.table)
setDT(dat)[, .(name = c(name, unlist(altNames))), by = id]
#       id  name
#  1: 1001  Joan
#  2: 1002  Jane
#  3: 1002 Janie
#  4: 1002 Janet
#  5: 1002   Jan
#  6: 1003  John
#  7: 1003   Jon
#  8: 1004  Bill
#  9: 1004  Will
# 10: 1005   Tom

基础 R 版本(使用由@rawr 添加的 df

with(df, {
    ns <- mapply(c, name, altNames)
    data.frame(id = rep(id, times=lengths(ns)), name=unlist(ns), row.names=NULL)
})
#     id  name
#1  1001  Joan
#2  1002  Jane
#3  1002 Janie
#4  1002 Janet
#5  1002   Jan
#6  1003  John
#7  1003   Jon
#8  1004  Bill
#9  1004  Will
#10 1005   Tom

使用tidyr,使用data.table清理数据后:

首先,修复数据:

library(data.table)
dat<-setDT(dat)
dat$altNames[sapply(dat$altNames, length) == 0] <- NA

现在 unnest 来自 tidyr 和一些 dplyr:

library(dplyr)
library(tidyr)
dat %>% unnest(altNames) %>%
        group_by(id) %>%
        do(unique(c(.[["name"]],.[["altNames"]])))

     id    V1
1  1001  Joan
2  1001    NA
3  1002  Jane
4  1002 Janie
5  1002 Janet
6  1002   Jan
7  1003  John
8  1003   Jon
9  1004  Bill
10 1004  Will
11 1005   Tom
12 1005    NA

它有 NA,但它们很容易用 %>% na.omit 删除。

我认为 data.table 是这一项的赢家。

这是一个完整的 dplyr + tidyr 解决方案,我的处理方式是:

library(dplyr)
library(tidyr)

df <- data_frame(
  id = c("1001", "1002","1003", "1004", "1005"), 
  name = c("Joan", "Jane", "John", "Bill", "Tom"), 
  altNames = list(character(0), c("Janie", "Janet", "Jan"), "Jon", "Will", character(0))
)

# Need some way to concatenate a list of vectors with a vectors
# in a "rowwise" way
vector_c <- function(...) {
  Map(c, ...)
}

df %>% 
  mutate(
    names = vector_c(name, altNames),
    altNames = NULL,
    name = NULL
  ) %>% 
  unnest(names)
#> Source: local data frame [10 x 2]
#> 
#>      id names
#> 1  1001  Joan
#> 2  1002  Jane
#> 3  1002 Janie
#> 4  1002 Janet
#> 5  1002   Jan
#> 6  1003  John
#> 7  1003   Jon
#> 8  1004  Bill
#> 9  1004  Will
#> 10 1005   Tom

大部分艰苦的工作都是由 tidyr::unnest() 完成的:它旨在获取带有列表列的数据框并取消嵌套,根据需要重复其他列。