合并数据框中的重复行并创建新列

时间:2018-04-07 11:05:26

标签: r dataframe

我正在尝试聚合数据框中的行,这些行的某些值类似,而其他值则如下所示:

  dataframe1 <- data.frame(Company_Name = c("KFC", "KFC", "KFC", "McD", "McD"), 
                        Company_ID = c(1, 1, 1, 2, 2),
                        Company_Phone = c("237389", "-", "-", "237002", "-"),
                       Employee_Name = c("John", "Mary", "Jane", "Joshua", 
                     "Anne"),
                     Employee_ID = c(1001, 1002, 1003, 2001, 2002))

我希望将相似值的行组合起来,并为不同的值创建新列,如下所示:

   dataframe2 <- data.frame(Company_Name = c("KFC", "McD"), 
                     Company_ID = c(1,  2),
                     Company_Phone = c("237389", "237002"),
                     Employee_Name1 = c("John", "Joshua" ),
                     Employee_ID1 = c(1001, 2001),
                     Employee_Name2 = c("Mary", "Anne"),
                     Employee_ID2 = c(1002, 2002),
                     Employee_Name3 = c("Jane", "na"),
                     Employee_ID3 = c(1003, "na"))

我检查了类似的问题,例如Combining duplicated rows in R and adding new column containing IDs of duplicatesR: collapse rows and then convert row into a new column,但我不希望用逗号分隔值,而是创建新列。

 # Company_Name Company_ID Company_Phone Employee_Name1 Employee_ID1 Employee_Name2 Employee_ID2 Employee_Name3 Employee_ID3
 #1          KFC          1        237389           John         1001           Mary         1002           Jane         1003
 #2          McD          2        237002         Joshua         2001           Anne         2002             na           na

提前谢谢。

3 个答案:

答案 0 :(得分:3)

使用的解决方案。 dat是最终输出。

library(tidyverse)

dat <- dataframe1 %>%
  mutate_if(is.factor, as.character) %>%
  mutate(Company_Phone = ifelse(Company_Phone %in% "-", NA, Company_Phone)) %>%
  fill(Company_Phone) %>%
  group_by(Company_ID) %>%
  mutate(ID = 1:n()) %>%
  gather(Info, Value, starts_with("Employee_")) %>%
  unite(New_Col, Info, ID, sep = "") %>%
  spread(New_Col, Value) %>%
  select(c("Company_Name", "Company_ID", "Company_Phone",
           paste0(rep(c("Employee_ID", "Employee_Name"), 3), rep(1:3, each = 2)))) %>%
  ungroup()

# View the result
dat %>% as.data.frame(stringsAsFactors = FALSE)
#   Company_Name Company_ID Company_Phone Employee_ID1 Employee_Name1 Employee_ID2 Employee_Name2 Employee_ID3 Employee_Name3
# 1          KFC          1        237389         1001           John         1002           Mary         1003           Jane
# 2          McD          2        237002         2001         Joshua         2002           Anne         <NA>           <NA>

答案 1 :(得分:3)

我们可以使用来自dcast的{​​{1}}来执行此操作,这可能需要多个data.table列。转换&#39; data.frame&#39;到&#39; data.table&#39; (value.var),按&#39; Company_Name&#39;分组,替换&#39; Company_Phone&#39;带有setDT(dataframe1)字母数字字符串的_元素,然后来自&#39; long&#39;的first广泛的&#39;通过指定&#39; Employee_Name&#39;和&#39; Employee_ID&#39;作为dcast

value.var

-output

library(data.table)
setDT(dataframe1)[, Company_Phone := first(Company_Phone), Company_Name]
res <- dcast(dataframe1, Company_Name + Company_ID + Company_Phone ~ 
       rowid(Company_Name), value.var  = c("Employee_Name", "Employee_ID"), sep='')

如果我们需要订购

res
#Company_Name Company_ID Company_Phone Employee_Name1 Employee_Name2 Employee_Name3 Employee_ID1 Employee_ID2 Employee_ID3
#1:          KFC          1        237389           John           Mary           Jane         1001         1002         1003
#2:          McD          2        237002         Joshua           Anne             NA         2001         2002           NA

答案 2 :(得分:2)

以下是结合dplyrcSplit

的其他方法
library(dplyr)
dataframe1 <- dataframe1 %>%
  group_by(Company_Name, Company_ID) %>%
  summarise_all(funs(paste((.), collapse = ",")))

library(splitstackshape)
dataframe1 <- cSplit(dataframe1, c("Company_Phone", "Employee_Name", "Employee_ID"), ",")

dataframe1
#   Company_Name Company_ID Company_Phone_1 Company_Phone_2 Company_Phone_3 Employee_Name_1 Employee_Name_2 Employee_Name_3 Employee_ID_1 Employee_ID_2 Employee_ID_3
#1:          KFC          1          237389               -               -            John            Mary            Jane          1001          1002          1003
#2:          McD          2          237002               -              NA          Joshua            Anne              NA          2001          2002            NA