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

时间:2015-07-02 22:55:32

标签: r dataframe dplyr

我有以下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和/或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))
)

4 个答案:

答案 0 :(得分:15)

这是一种可能的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

答案 1 :(得分:10)

基础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

答案 2 :(得分:5)

这是一个完整的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()完成的:它的设计目的是将数据框与列表列一起取出,然后根据需要重复其他列。

答案 3 :(得分:4)

使用tidyr清除数据后使用data.table

首先,修复数据:

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

unnest来自tidyrdplyr

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

它有NAs,但可以使用%>% na.omit轻松删除它们。

我认为data.table是这方面的赢家。