查找所有重复行,包括“具有较小下标的元素”

Posted

技术标签:

【中文标题】查找所有重复行,包括“具有较小下标的元素”【英文标题】:Finding ALL duplicate rows, including "elements with smaller subscripts" 【发布时间】:2011-12-12 20:33:36 【问题描述】:

R 的duplicated 返回一个向量,显示向量或数据框的每个元素是否是具有较小下标的元素的副本。所以如果 5 行数据帧的第 3、4 和 5 行相同,duplicated 会给我向量

FALSE, FALSE, FALSE, TRUE, TRUE

但在这种情况下,我实际上想要得到

FALSE, FALSE, TRUE, TRUE, TRUE

也就是说,我想知道一行是否也被带有更大下标的行所复制。

【问题讨论】:

【参考方案1】:

duplicated 有一个 fromLast 参数。 ?duplicated 的“示例”部分向您展示了如何使用它。只需调用duplicated 两次,一次是fromLast=FALSE,一次是fromLast=TRUE,然后取TRUE 所在的行。


一些迟到的编辑: 您没有提供可重现的示例,因此这是由@jbaums 提供的插图

vec <- c("a", "b", "c","c","c") 
vec[duplicated(vec) | duplicated(vec, fromLast=TRUE)]
## [1] "c" "c" "c"

编辑:还有一个数据框的例子:

df <- data.frame(rbind(c("a","a"),c("b","b"),c("c","c"),c("c","c")))
df[duplicated(df) | duplicated(df, fromLast=TRUE), ]
##   X1 X2
## 3  c  c
## 4  c  c

【讨论】:

等一下,我刚刚进行了测试,发现我错了:x &lt;- c(1:9, 7:10, 5:22); y &lt;- c(letters, letters[1:5]); test &lt;- data.frame(x, y); test[duplicated(test$x) | duplicated(test$x, fromLast=TRUE), ] 退回了所有 7、8 和 9 的三个副本。为什么会这样? 因为无论你是从头开始还是从前面开始,都会捕获中间的。例如,duplicated(c(1,1,1))duplicated(c(1,1,1,), fromLast = TRUE) 给出 c(FALSE,TRUE,TRUE)c(TRUE,TRUE,FALSE)。在这两种情况下,中间值为TRUE。取两个向量的| 得到c(TRUE,TRUE,TRUE)【参考方案2】:

您需要组装duplicated 值的集合,应用unique,然后使用%in% 进行测试。与往常一样,一个示例问题将使这个过程变得活跃。

> vec <- c("a", "b", "c","c","c")
> vec[ duplicated(vec)]
[1] "c" "c"
> unique(vec[ duplicated(vec)])
[1] "c"
>  vec %in% unique(vec[ duplicated(vec)]) 
[1] FALSE FALSE  TRUE  TRUE  TRUE

【讨论】:

同意。甚至可能会减慢处理速度,但不太可能减慢速度。 非常正确。 OP 没有提供数据示例来测试数据框中的“曾经重复”的行。我认为我使用duplicatedunique%in% 的建议可以很容易地推广到一个数据框,如果一个人首先paste 每一行都有一个不寻常的分隔符。 (接受的答案更好。)【参考方案3】:

可以使用dplyr 获得数据框中的重复行

library(tidyverse)
df = bind_rows(iris, head(iris, 20)) # build some test data
df %>% group_by_all() %>% filter(n()>1) %>% ungroup()

要排除某些列 group_by_at(vars(-var1, -var2)) 可以改为对数据进行分组。

如果实际需要行索引而不仅仅是数据,您可以先添加它们,如下所示:

df %>% add_rownames %>% group_by_at(vars(-rowname)) %>% filter(n()>1) %>% pull(rowname)

【讨论】:

很好地使用了n()。不要忘记取消组合生成的数据框。 @qwr 我已调整答案以取消组合结果 @HolgerBrandl,@qwr,一般答案很有用,但我不明白如何选择要排除的列。 group_by_at(vars(-var1, -var2)) 中的“vars”指的是什么? var1var2 列名称是否在名为 vars 的数据表中?我认为负号表示排斥,对吗?所以剩下的过程(filterungroup)作用于数据表vars 中的其余列,但不包括var1var2,对吗?很抱歉这么迂腐,但我经常在速记方面遇到问题! vars 是 dplyr 中的一个方法,参见 dplyr.tidyverse.org/reference/vars.html 。 var1, var2 确实是指要从重复检查中排除的列名。对建议解决方案中的分组变量进行重复评估。事实上,否定意味着排斥。 group_by_all()group_by_at() 在 dplyr 的最新版本中已被取代。现在你可以这样做了:iris %&gt;% group_by(across()) %&gt;% filter(n() &gt; 1) %&gt;% ungroup()【参考方案4】:

我有same question,如果我没记错的话,这也是一个答案。

vec[col %in% vec[duplicated(vec$col),]$col]

不知道哪个更快,但我目前使用的数据集不够大,无法进行会产生显着时间间隔的测试。

【讨论】:

这个答案似乎使用vec 作为原子向量和数据框。我怀疑使用实际的 datframe 会失败。【参考方案5】:

这是@Joshua Ulrich 作为函数的解决方案。这种格式允许您以与使用 duplicated() 相同的方式使用此代码:

allDuplicated <- function(vec)
  front <- duplicated(vec)
  back <- duplicated(vec, fromLast = TRUE)
  all_dup <- front + back > 0
  return(all_dup)

用同样的例子:

vec <- c("a", "b", "c","c","c") 
allDuplicated(vec) 
[1] FALSE FALSE  TRUE  TRUE  TRUE

【讨论】:

【参考方案6】:

我遇到了类似的问题,但我需要通过特定列中的值来识别重复的行。我想出了以下 dplyr 解决方案:

df <- df %>% 
  group_by(Column1, Column2, Column3) %>% 
  mutate(Duplicated = case_when(length(Column1)>1 ~ "Yes",
                            TRUE ~ "No")) %>%
  ungroup()

代码按特定列对行进行分组。如果组的长度大于 1,则代码会将组中的所有行标记为重复。完成后,您可以使用Duplicated 列进行过滤等。

【讨论】:

【参考方案7】:

如果您对某些列的重复行感兴趣,可以使用 plyr 方法:

ddply(df, .(col1, col2), function(df) if(nrow(df) > 1) df else c())

使用 dplyr 添加计数变量:

df %>% add_count(col1, col2) %>% filter(n > 1)  # data frame
df %>% add_count(col1, col2) %>% select(n) > 1  # logical vector

对于重复行(考虑所有列):

df %>% group_by_all %>% add_tally %>% ungroup %>% filter(n > 1)
df %>% group_by_all %>% add_tally %>% ungroup %>% select(n) > 1

这些方法的好处是您可以指定多少重复作为截止值。

【讨论】:

【参考方案8】:

这更新了@Holger Brandl 的答案以反映 dplyr 的最新版本(例如 1.0.5),其中 group_by_all()group_by_at() 已被取代。帮助文档建议改用across()

因此,要获取所有重复的行,您可以执行以下操作: iris %&gt;% group_by(across()) %&gt;% filter(n() &gt; 1) %&gt;% ungroup()

要包含此类行的索引,请添加“rowid”列,但将其从分组中排除: iris %&gt;% rowid_to_column() %&gt;% group_by(across(!rowid)) %&gt;% filter(n() &gt; 1) %&gt;% ungroup()

在上面添加%&gt;% pull(rowid),你会得到一个索引向量。

【讨论】:

以上是关于查找所有重复行,包括“具有较小下标的元素”的主要内容,如果未能解决你的问题,请参考以下文章

Pandas:查找不在另一个DataFrame中的DataFrame行[重复]

mysql中如何找出重复数据的所有行

查找重复行的索引 [重复]

查找重复行的索引 [重复]

在拆分为多个文件的大型数据框中查找重复行和包含重复行的文件

在 GIT 中查找添加了特定字符串的提交 [重复]