【问题标题】:Remove duplicated rows using dplyr使用 dplyr 删除重复的行
【发布时间】:2014-05-22 11:35:46
【问题描述】:

我有一个这样的 data.frame -

set.seed(123)
df = data.frame(x=sample(0:1,10,replace=T),y=sample(0:1,10,replace=T),z=1:10)
> df
   x y  z
1  0 1  1
2  1 0  2
3  0 1  3
4  1 1  4
5  1 0  5
6  0 1  6
7  1 0  7
8  1 0  8
9  1 0  9
10 0 1 10

我想根据前两列删除重复的行。预期输出 -

df[!duplicated(df[,1:2]),]
  x y z
1 0 1 1
2 1 0 2
4 1 1 4

我正在专门寻找使用dplyr 包的解决方案。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是使用dplyr >= 0.5 的解决方案。

    library(dplyr)
    set.seed(123)
    df <- data.frame(
      x = sample(0:1, 10, replace = T),
      y = sample(0:1, 10, replace = T),
      z = 1:10
    )
    
    > df %>% distinct(x, y, .keep_all = TRUE)
        x y z
      1 0 1 1
      2 1 0 2
      3 1 1 4
    

    【讨论】:

    • 这个解决方案似乎比 Hadley 提供的解决方案快得多(在我的例子中是 10 倍)。
    • 从技术上讲,这也是 Hadley 提供的解决方案 :-)
    • 您通过排列解决了删除哪些行的问题,它保留了第一行。
    【解决方案2】:

    注意dplyr 现在包含用于此目的的 distinct 函数。

    原答案如下:


    library(dplyr)
    set.seed(123)
    df <- data.frame(
      x = sample(0:1, 10, replace = T),
      y = sample(0:1, 10, replace = T),
      z = 1:10
    )
    

    一种方法是分组,然后只保留第一行:

    df %>% group_by(x, y) %>% filter(row_number(z) == 1)
    
    ## Source: local data frame [3 x 3]
    ## Groups: x, y
    ## 
    ##   x y z
    ## 1 0 1 1
    ## 2 1 0 2
    ## 3 1 1 4
    

    (在 dplyr 0.2 中,您不需要虚拟 z 变量,只需 能写row_number() == 1)

    我也一直在考虑添加一个 slice() 函数 像这样工作:

    df %>% group_by(x, y) %>% slice(from = 1, to = 1)
    

    或者可能是unique() 的变体,可以让您选择哪个 要使用的变量:

    df %>% unique(x, y)
    

    【讨论】:

    • @dotcomken 在那之前也可以只使用df %&gt;% group_by(x, y) %&gt;% do(head(.,1))
    • @MahbubulMajumder 可以,但速度很慢。 dplyr 0.3 将有 distinct()
    • @hadley 我喜欢 unique() 和 distinct() 函数,但是,它们都从数据框中删除了第二个重复项。如果我想删除所有第一次遇到的重复值怎么办?怎么可能做到这一点?感谢您的帮助!
    • @MvZB - 你不只是安排(desc()) 然后使用 distinct 吗?
    • 我确信有一个简单的解决方案,但如果我想去掉两个重复的行怎么办?我经常使用与生物样本相关的元数据,如果我有重复的样本 ID,我经常不能确定哪一行有正确的数据。最安全的选择是转储两者以避免错误的元数据关联。除了列出重复的样本 ID 并过滤掉具有这些 ID 的行之外,还有什么简单的解决方案吗?
    【解决方案3】:

    为了完整起见,以下内容也适用:

    df %>% group_by(x) %>% filter (! duplicated(y))
    

    不过,我更喜欢使用 distinct 的解决方案,而且我怀疑它也更快。

    【讨论】:

      【解决方案4】:

      大多数时候,最好的解决方案是使用来自 dplyr 的 distinct(),正如已经建议的那样。

      但是,这是使用 dplyr 中的 slice() 函数的另一种方法。

      # Generate fake data for the example
        library(dplyr)
        set.seed(123)
        df <- data.frame(
          x = sample(0:1, 10, replace = T),
          y = sample(0:1, 10, replace = T),
          z = 1:10
        )
      
      # In each group of rows formed by combinations of x and y
      # retain only the first row
      
          df %>%
            group_by(x, y) %>%
            slice(1)
      

      与使用distinct()函数的区别

      此解决方案的优势在于,它可以明确从原始数据帧中保留哪些行,并且可以与 arrange() 函数很好地配对。

      假设您拥有客户销售数据,并且您希望为每位客户保留一条记录,并且您希望该记录是他们最近一次购买的记录。然后你可以写:

      customer_purchase_data %>%
         arrange(desc(Purchase_Date)) %>%
         group_by(Customer_ID) %>%
         slice(1)
      

      【讨论】:

        【解决方案5】:

        在 R 中为精简数据集选择列时,您通常会出现重复。

        这两行给出了相同的结果。每个输出一个唯一的数据集,只有两个选定的列:

        distinct(mtcars, cyl, hp);
        
        summarise(group_by(mtcars, cyl, hp));
        

        【讨论】:

          【解决方案6】:

          如果要查找重复的行,可以使用 find_duplicates from hablar:

          library(dplyr)
          library(hablar)
          
          df <- tibble(a = c(1, 2, 2, 4),
                       b = c(5, 2, 2, 8))
          
          df %>% find_duplicates()
          

          【讨论】:

            猜你喜欢
            • 2018-04-07
            • 2018-01-29
            • 2023-03-09
            • 1970-01-01
            • 1970-01-01
            • 2020-07-06
            • 2021-09-24
            • 1970-01-01
            • 2019-10-29
            相关资源
            最近更新 更多