如果一行与前一行相同(除了一列),则删除该行

3

I have the following dataframe

x <- data.frame(id = c(1:6), 
                a = c('a', 'b', 'b', 'a', 'a', 'c'), 
                b = rep(2, 6), 
                c = c(5, 4, 4, 5, 5, 2))

> x
  id a b c
1  1 a 2 5
2  2 b 2 4
3  3 b 2 4
4  4 a 2 5
5  5 a 2 5
6  6 c 2 2

I want to end up with

  id a b c
1  1 a 2 5
2  2 b 2 4
4  4 a 2 5
6  6 c 2 2

要求是,如果一行与前一行相同,但id列除外,则将该行删除。如果它与上面的某一列相同,但不是紧接着的前一列,则不希望将其删除。例如,id4与id1相同,但不会被删除,因为它不是紧接着id1。

任何帮助都将不胜感激。

2个回答

3

我们可以使用基本R

x[!c(FALSE, !rowSums(x[-1, -1] != x[-nrow(x), -1])),]
#  id a b c
#1  1 a 2 5
#2  2 b 2 4
#4  4 a 2 5
#6  6 c 2 2

这个方法可以工作,但我将其放在一个通用函数中,无法保证id列是第一列,因此使用此方法可能会有危险。 - user1165199
1
如果您需要使用名称nm1 <- setdiff(names(x), "id"); x[!c(FALSE, !rowSums(x[-1, nm1] != x[-nrow(x), nm1])),],请注意。 - akrun

2

这里有一种使用dplyr中的lag函数的方法。思路是创建一个关键列,并检查它是否与前一个相同。

library(dplyr)
x %>% 
  mutate(key=paste(a, b, c, sep="|")) %>%
  filter(key != lag(key, default="0")) %>% 
  select(-key)

谢谢Jason,但是在我的实际情况中,我有比a、b和c更多的列。有没有一种方法可以不用命名它们就能完成呢? - user1165199
1
我认为在这种情况下我们需要非标准评估。但是,我没有想出使用 mutate_ 创建键的方法。我最终得到的是:x$key <- apply(x[names(x[-1])], 1, function(x) paste(x, collapse="|")) - JasonWang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接