R的duplicated
函数返回一个向量,显示向量或数据框中的每个元素是否是具有较小下标的元素的副本。因此,如果一个5行数据框的第3、4和5行相同,则duplicated
将给我这个向量。
FALSE, FALSE, FALSE, TRUE, TRUE
但在这种情况下,我确实想要获取
FALSE, FALSE, TRUE, TRUE, TRUE
也就是说,我想知道一个行是否被具有更大下标的另一行所重复。
R的duplicated
函数返回一个向量,显示向量或数据框中的每个元素是否是具有较小下标的元素的副本。因此,如果一个5行数据框的第3、4和5行相同,则duplicated
将给我这个向量。
FALSE, FALSE, FALSE, TRUE, TRUE
但在这种情况下,我确实想要获取
FALSE, FALSE, TRUE, TRUE, TRUE
也就是说,我想知道一个行是否被具有更大下标的另一行所重复。
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
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
使用 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()
。别忘了取消分组后的数据框。 - qwrgroup_by_at(vars(-var1,-var2))
中,“vars”是指什么?var1
和var2
是datatable vars
中的列名吗?我假设负号表示排除,那么进程的其余部分(filter
和ungroup
)作用于datatable vars
中其余的列,但不包括var1
和var2
,对吗?抱歉这么啰嗦,但我经常在快速简写方面遇到问题! - W Barkergroup_by_all()
and group_by_at()
have been superseded in recent versions of dplyr. Now you can do this:iris %>% group_by(across()) %>% filter(n() > 1) %>% ungroup()
- MCornejo这是@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
我曾经有过类似的问题,而且如果我没有记错,这也是一个答案。
vec[col %in% vec[duplicated(vec$col),]$col]
不过,我目前使用的数据集还不够大,无法进行产生显著时间差的测试,因此不知道哪一个更快。
vec
用作原子向量和数据框。我怀疑如果使用实际的数据框,它会失败。 - IRTFMvctrs::vec_duplicate_detect()
的工作原理。# on a vector
vctrs::vec_duplicate_detect(c(1, 2, 1))
#> [1] TRUE FALSE TRUE
# on a data frame
vctrs::vec_duplicate_detect(mtcars[c(1, 2, 1),])
#> [1] TRUE FALSE TRUE
由 reprex package(v2.0.1)于2022年7月19日创建
我遇到了类似的问题,但是我需要通过特定列中的值来识别重复的行。我想出了以下 dplyr 解决方案:
df <- df %>%
group_by(Column1, Column2, Column3) %>%
mutate(Duplicated = case_when(length(Column1)>1 ~ "Yes",
TRUE ~ "No")) %>%
ungroup()
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
这些方法的好处是您可以指定重复项的截止数量。
data %>% mutate(duplicate_id = if_else(id %in% id[duplicated(id)], TRUE, FALSE))
这篇文章更新了@Holger Brandl的答案,以反映dplyr的最新版本(例如1.0.5),其中group_by_all()
和group_by_at()
已被取代。帮助文档建议使用across()
代替。
因此,要获取所有存在重复的行,可以执行以下操作:
iris %>% group_by(across()) %>% filter(n() > 1) %>% ungroup()
要包括这些行的索引,请添加一个“rowid”列,但将其排除在分组之外:
iris %>% rowid_to_column() %>% group_by(across(!rowid)) %>% filter(n() > 1) %>% ungroup()
在上述操作后附加%>% pull(rowid)
,您将获得一个索引向量。
x <- c(1:9, 7:10, 5:22); y <- c(letters, letters[1:5]); test <- data.frame(x, y); test[duplicated(test$x) | duplicated(test$x, fromLast=TRUE), ]
返回了三个7、8和9的副本。为什么会这样? - JoeM05duplicated(c(1,1,1))
和duplicated(c(1,1,1), fromLast=TRUE)
分别返回c(FALSE,TRUE,TRUE)
和c(TRUE,TRUE,FALSE)
。在两种情况下,中间的值都是TRUE
。 对这两个向量取|
运算符可得c(TRUE, TRUE, TRUE)
。 - Brandon