【问题标题】:How can I combine rows within the same data frame in R (based on duplicate values under a specific column)?如何在 R 中合并同一数据框中的行(基于特定列下的重复值)?
【发布时间】:2015-05-16 10:24:46
【问题描述】:

df 中 2 个(组成)示例行的示例:

userid   facultyid  courseid schoolid
167       265        NA       1678  
167       71111      301      NA

假设我有几百个重复的用户 ID,就像上面的例子一样。但是,绝大多数 userid 具有不同的值。

除非第一个值为 NA(在这种情况下,NA 将重新填充任何值)从第二行开始)?

本质上,从上面的示例中得出,我的理想输出将包含:

userid   facultyid  courseid schoolid
167       265        301       1678  

【问题讨论】:

    标签: r duplicates append combiners


    【解决方案1】:
    aggregate(x = df1, by = list(df1$userid), FUN = function(x) na.omit(x)[1])[,-1]
    

    或使用dplyr库:

    library(dplyr)
    
    df1 %>%
      group_by(userid) %>%
      summarise_each(funs(first(na.omit(.))))
    

    【讨论】:

    • 谢谢@bergant!您能否简要解释一下您的函数中的不同参数?
    • 函数 (FUN) 中的变量 x 是一列(向量)值。它为 data.frame 中的每一列调用,并且只为具有相同用户 ID 的值调用。这是一个分组操作 - 组由 by 参数定义。
    【解决方案2】:
    # initialize a vector that will contain row numbers which should be erased
    rows.to.erase <- c()
    
    # loop over the rows, starting from top
    for(i in 1:(nrow(dat)-1)) {
      if(dat$userid[i] == dat$userid[i+1]) {
        # loop over columns to recuperate data when a NA is present
        for(j in 2:4) {
          if(is.na(dat[i,j]))
            dat[i,j] <- dat[i+1,j]
        }
        rows.to.erase <- append(rows.to.erase, i+1)
      }
    }
    
    dat.clean <- dat[-rows.to.erase,]
    dat.clean
    #   userid facultyid courseid schoolid
    # 1    167       265      301     1678
    

    【讨论】:

      【解决方案3】:

      这是使用ddply 的另一种方法:

      # requires the plyr package
      library(plyr)
      
      # Your example dataframe with added lines
      schoolex <- data.frame(userid = c(167, 167, 200, 203, 203), facultyid = c(265, 71111, 200, 300, NA), 
                              courseid = c(NA, 301, 302, 303, 303), schoolid = c(1678, NA, 1678, NA, 1678))
      
      schoolex_duprm <- ddply(schoolex, .(userid), summarize, facultyid2 = facultyid[!is.na(facultyid)][1], 
                                     courseid2 = courseid[!is.na(courseid)][1], 
                                     schoolid2 = schoolid[!is.na(schoolid)][1])
      

      【讨论】:

      • 嗨,哈里森,非常感谢您的回答!如果我有近 1000 个列/变量,是否有更简单的方法来复制您的函数,或者我必须为每个列/变量写出 first() 参数?
      • @bergant 为大量列提供了解决方案...请参阅下面的答案
      【解决方案4】:

      这是 plyr 的一个简单的单线。我写的比你问的更笼统一些:

       a <- data.frame(x=c(1,2,3,1,2,3,1,2,3),y=c(2,3,1,1,2,3,2,3,1),
             z=c(NA,1,NA,2,NA,3,4,NA,5),zz=c(1,NA,2,NA,3,NA,4,NA,5))
      
       ddply(a,~x+y,summarize,z=first(z[!is.na(z)]),zz=first(zz[!is.na(zz)]))
      

      具体回答原问题,如果你的数据框名为a,:

       ddply(a,~userid,summarize,facultyid=first(facultyid[!is.na(facultyid)]),
               courseid=first(courseid[!is.na(courseid)],
               schoolid=first(schoolid[!is.na(schoolid)])
      

      【讨论】:

      • 嗨彼得,非常感谢您的回答!如果我有近 1000 个列/变量,是否有更简单的方法来复制您的函数,或者我必须为每个列/变量写出 first() 参数?
      猜你喜欢
      • 2023-03-09
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 2020-05-16
      • 2011-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多