使用dplyr删除重复的行


128

我有一个这样的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包的解决方案。

Answers:


137

注意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)

4
@dotcomken在此之前也可以使用df %>% group_by(x, y) %>% do(head(.,1))
Holger Brandl

16
@MahbubulMajumder可以工作,但是速度很慢。dplyr 0.3将会有distinct()
hadley 2014年

3
@hadley我喜欢unique()和distinct()函数,但是,它们都从数据框中删除了第二个重复项。如果我想删除所有重复值的第一次匹配怎么办?怎么办呢?谢谢你的帮助!
FlyingDutch

2
@MvZB-您不只是排列(desc())然后使用distinct吗?
伍德斯托克

我敢肯定有一个简单的解决方案,但是如果我想摆脱两个重复的行怎么办?我经常使用与生物样品相关的元数据,如果我有重复的样品ID,通常不能确定哪一行具有正确的数据。最安全的选择是将两者都转储以避免错误的元数据关联。除了列出重复的样品ID并过滤出具有这些ID的行之外,还有其他简单的解决方案吗?
glongo_fishes

191

这是使用的解决方案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

3
该解决方案似乎比Hadley提供的解决方案要快得多(在我的情况下是10倍)。
Calimo 2014年

101
从技术上讲,这也是Hadley提供的解决方案:-)
Tyler Rinker

27

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

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

但是,我更喜欢使用的解决方案distinct,并且我怀疑它也更快。


7

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

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

# 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)

3

当选择R中的列以减少数据集时,您通常会得到重复。

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

distinct(mtcars, cyl, hp);

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

1

如果你想找到是重复的,你可以使用行find_duplicateshablar

library(dplyr)
library(hablar)

df <- tibble(a = c(1, 2, 2, 4),
             b = c(5, 2, 2, 8))

df %>% find_duplicates()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.