仅基于上一行删除重复行

5

我正在尝试从数据框中仅基于前一行删除重复行。函数duplicateunique会删除所有重复项,只留下唯一的行,这不是我想要的。

我在此处使用循环演示了问题。我需要向量化这个过程,因为我的实际数据集太大,无法在循环中使用。

x <- c(1,1,1,1,3,3,3,4)
y <- c(1,1,1,1,3,3,3,4)
z <- c(1,2,1,1,3,2,2,4)
xy <- data.frame(x,y,z)

xy
  x y z
1 1 1 1
2 1 1 2
3 1 1 1
4 1 1 1 #this should be removed
5 3 3 3
6 3 3 2
7 3 3 2 #this should be removed
8 4 4 4

# loop that produces desired output
toRemove <- NULL
for (i in 2:nrow(xy)){
   test <- as.vector(xy[i,] == xy[i-1,])
   if (!(FALSE %in% test)){ 
      toRemove <- c(toRemove, i) #build a vector of rows to remove
   }
}
xy[-toRemove,] #exclude rows
  x y z
1 1 1 1
2 1 1 2
3 1 1 1
5 3 3 3
6 3 3 2
8 4 4 4

我尝试使用dplyr的lag函数,但它只适用于单个列,当我尝试在所有3列上运行它时,它不起作用。 ifelse(xy[,1:3] == lag(xy[,1:3],1), NA, xy[,1:3]) 有任何建议如何完成这个任务吗?

zx8754的方法绝对是正确的。但是,我想提一下,只要使用mutate_each,就可以使用dplyr::lag来完成这个操作。例如,xy %>% mutate_each(funs(oneL = . - lag(.))) %>% mutate(dup = rowSums(select(. ,contains("oneL"))))%>% filter(dup != 0 | is.na(dup)) %>% select(x,y,z) - Jacob H
2个回答

6

看起来我们想要删除与上面一行相同的行:

# make an index, if cols not same as above
ix <- c(TRUE, rowSums(tail(xy, -1) == head(xy, -1)) != ncol(xy))

# filter
xy[ix, ]

这个方法是有效的,但你能解释一下语法,特别是 != ncol(xy) 部分吗?(我看到它将相等测试的数据框转换为向量,但我无法弄清楚它是如何工作的)。我原本期望 rowSums 可以删除相同和的行(这可能允许不同的数字加起来得到相同的值)。但我测试了几种情况,发现这种方法并没有删除那些行。 - Lloyd Christmas
我正在创建一个名为'keep'的列表,其中包含所有值为TRUE的项目。首先找到第一个值为TRUE的项目,并将其保留。然后,逐行比较每行的总和与前一行的总和,如果与ncol(在此情况下为3)不相同,则保留该行,即保留那些与上述行不同的行。希望这样清楚明了。 - zx8754

-3
为什么不在迭代列表的同时跟踪前一行以将其与下一行进行比较?
如果某个时刻条件成立:请记住该行位置并从列表中删除它,然后从列表开头开始迭代。 不要在迭代时删除行,因为这会导致并发修改错误。

欢迎来到SO!与zx8754的方法相比,您提出的方法非常低效。R是一种高级语言,因此应避免使用for循环。特别是由于利用BLAS的子集操作非常快速。如果您提供代码,这对OP会很有帮助。 - Jacob H

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