【问题标题】:Remove duplicates based on 2nd column condition根据第二列条件删除重复项
【发布时间】:2014-09-21 19:15:12
【问题描述】:

我正在尝试根据不同列上的最大值从数据框中删除重复行

所以,对于数据框:

df<-data.frame (rbind(c("a",2,3),c("a",3,4),c("a",3,5),c("b",1,3),c("b",2,6),c("r",4,5))
  colnames(df)<-c("id","val1","val2")

id val1 val2

  a    2    3

  a    3    4

  a    3    5

  b    1    3

  b    2    6

  r    4    5

我想按 id 删除所有重复项,条件是对应的行没有 val2 的最大值。

因此数据框应该变成:

  a    3    5

  b    2    6

  r    4    5

-> 删除所有重复项,但保留 df$val2 for subset(df, df$id=="a") 的最大值的行

【问题讨论】:

    标签: r


    【解决方案1】:

    使用base R。在这里,列是factors。确保将其转换为numeric

     df$val2 <- as.numeric(as.character(df$val2))
     df[with(df, ave(val2, id, FUN=max)==val2),]
     #  id val1 val2
     #3  a    3    5
     #5  b    2    6
     #6  r    4    5
    

    或使用dplyr

     library(dplyr)
     df %>% 
        group_by(id) %>% 
        filter(val2==max(val2))
     #   id val1 val2
     #1  a    3    5
     #2  b    2    6
     #3  r    4    5
    

    【讨论】:

    • 您可能需要将 mutate(val2 = as.numeric(as.character(val2))) %&gt;% 添加到您的 dplyr 解决方案中
    • @David Arenburg 我使用了之前解决方案中转换后的df。是的,你是对的,但我猜 OP 在构建示例时可能犯了一个错误。
    • (+1) 在我要去之前一秒钟发布这两个 :)
    • 这很好用,但如果我有数百万行且重复项很少,则需要相当长的时间——即代码还必须创建数百万只包含 1 个元素的组。在这种情况下有什么方法可以改进解决方案吗?
    • @user3032689 with data.table setDT(df)[order(-val2), head(.SD, 1), id]
    【解决方案2】:

    一种可能的方法是使用data.table

    library(data.table)
    setDT(df)[, .SD[which.max(val2)], by = id]
    ##    id val1 val2
    ## 1:  a    3    5
    ## 2:  b    2    6
    ## 3:  r    4    5
    

    【讨论】:

    • 这太棒了!谢谢!但是,我正在使用 R 与 Spotfire 的集成,并且在安装包、操作系统之间的兼容性、版本、软件版本、统计服务等方面存在问题,如果有一个不需要额外库或循环的解决方案,那就太好了。
    • 非常好!但是使用 setDT(df)[df[, .I[which.max(val2)], by = id]$V1] 有一种更快的方法。希望它对更大的数据集有所帮助。
    【解决方案3】:

    我希望你的数据是这样设置的

    df <- data.frame (id = c(rep("a", 3), rep("b", 2), "r"),
                      val1 = c(2, 3, 3, 1, 2, 4), val2 = c(3, 4, 5, 3, 6, 5))
    

    你可以做一个split-unsplit

    > unsplit(lapply(split(df, df$id), function(x) {
          if(nrow(x) > 1) {
              x[duplicated(x$id) & x$val2 == max(x$val2),]
          } else {
              x
          }
      }), levels(df$id))
    #   id val1 val2
    # 3  a    3    5
    # 5  b    2    6
    # 6  r    4    5
    

    您也可以使用Reduce(rbind, ...)do.call(rbind, ...) 代替unsplit

    【讨论】:

      【解决方案4】:

      另一个

      df %>% group_by(id) %>%
               slice(which.max(val2))
      
        id   val1  val2
         a    3     5
         b    2     6
         r    4     5
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-20
        • 2020-02-17
        • 1970-01-01
        • 1970-01-01
        • 2014-03-14
        相关资源
        最近更新 更多