识别 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_grid
和 purrr::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
我有一个这样的字符向量列表:
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_grid
和 purrr::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