识别 R 中字符向量列表中的重复项

Identifying duplicates in a list of character vectors in R

我有一个这样的字符向量列表:

my_list <- list(c('a','b','c','d','e'),c('e','f','g'),c('h','i','j'))
names(my_list) <- c("group1","group2","group3")

而且我想要一种简单的方法来测试 my_list 列表中 3 个 groups/vectors 中任意字母的重复项。因此,例如,“e”同时出现在第 1 组和第 2 组中,因此这将是重复的。如果 2 个或多个组中至少有一个或多个重复项,只要 return 符合逻辑,任何简单的事情都是理想的。因此,FALSE return 意味着每个组中的字母仅对该组唯一(在我的示例中显然不是这种情况)。

非常感谢!

我们可以 stack 命名的 list 到两列 data.frame,使用 table 获取频率计数,使用 [=17= 按列检查重复项] 在逻辑向量上和 return 与 names 出现超过 1

names(which(colSums(table(stack(my_list)[2:1])> 0) > 1))
[1] "e"

或者稍微紧凑一些

 names(which(table(unlist(my_list)) > 1))
[1] "e"

如果我们想要一个逻辑列

library(dplyr)
library(tidyr)
library(tibble)
enframe(my_list) %>%
   unnest(value) %>% 
  group_by(value) %>%
   mutate(flag = any(n_distinct(name) > 1)) %>% 
 group_by(name) %>% 
  summarise(flag = any(flag))

-输出

# A tibble: 3 × 2
  name   flag 
  <chr>  <lgl>
1 group1 TRUE 
2 group2 TRUE 
3 group3 FALSE

你可以这样做:

subset(stack(my_list), duplicated(values))$values
[1] "e"

如果您需要判断一个组中的所有值是否对该组都是唯一的,您可以这样做:

result <- setNames(logical(length(my_list)), names(my_list))

result[unique(unlist(Filter(\(x)length(x)>1,
                            unstack(rev(stack(my_list))))))] <- TRUE
result
group1 group2 group3 
  TRUE   TRUE  FALSE 

甚至:

stack(my_list) %>%
  mutate(dups = duplicated(values) | duplicated(values, f = T)) %>%
  group_by(ind) %>%
  summarise(logic = any(dups))

# A tibble: 3 x 2
  ind    logic
  <fct>  <lgl>
1 group1 TRUE 
2 group2 TRUE 
3 group3 FALSE

可以使用

生成二进制输出
any(duplicated(unlist(my_list)))
[1] TRUE

正如@sindri_baldur 在评论中正确指出的那样,如果重复项出现在组中,则应使用 unique 进行处理,如果需要:

any(duplicated(unlist(lapply(my_list, unique))))
[1] TRUE

或另一个base R替代

anyDuplicated(unlist(lapply(my_list, unique))) > 1
[1] TRUE

另一种可能的解决方案,基于 tidyr::expand_gridpurrr::pmap_lgl

library(tidyverse)

my_list <- list(c('a','b','c','d','e'),c('e','f','g'),c('h','i','j'))
names(my_list) <- c("group1","group2","group3")

expandg <- expand_grid(names(my_list), names(my_list))

pmap_lgl(expandg, ~ any(my_list[[.x]] %in% my_list[[.y]])) %>% 
  bind_cols(id1 = expandg[[1]], id2 = expandg[[2]], value = .) %>% 
  group_by(Group = id1) %>% summarise(value = any(value[id1 != id2]))

#> # A tibble: 3 × 2
#>   Group  value
#>   <chr>  <lgl>
#> 1 group1 TRUE 
#> 2 group2 TRUE 
#> 3 group3 FALSE