使用 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
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包。

170405 次浏览

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

下面是使用 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

为了完整起见,下面的方法同样适用:

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

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

当为缩减后的数据集选择 R 中的列时,通常会出现重复的列。

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

distinct(mtcars, cyl, hp);


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

大多数情况下,最好的解决方案是使用 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)

如果你想找到重复的行,你可以使用 hablar中的 find_duplicates:

library(dplyr)
library(hablar)


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


df %>% find_duplicates()