基于至少一个共同值对 Id 进行分组

Ano*_*n R 5 reduce r accumulate purrr

我有一个列表,其元素是整数,如果这些元素至少共享一个值,我想累积这些元素。对于那些与其他元素不共享任何价值观的元素,我希望它们保持原样。这是我的样品日期:

x <- list(c(1, 2), c(1, 2, 3), c(2, 3, 4), c(3, 4, 5), c(4, 5, 8), c(6, 9, 7), 7, c(5, 8), 10, 11)
Run Code Online (Sandbox Code Playgroud)

这是我想要的输出:

desired_reult <- list(c(1, 2, 3, 4, 5, 8), 
                      c(6, 9, 7), 
                      10, 
                      11)
Run Code Online (Sandbox Code Playgroud)

我想先用reduceaccumulate函数来做,purrrtidyverse欢迎任何其他解决方案。到目前为止,我已经尝试过这个解决方案,但它只给了我一个union,显然放弃了其余的:

x %>% 
  reduce(~ if(any(.x %in% .y)) union(.x, .y) else .x)

[1] 1 2 3 4 5 8
Run Code Online (Sandbox Code Playgroud)

一般来说,我正在寻找一种将整数 (id) 与常见值(如某种聚类)进行分组的方法,但不幸的是,到目前为止,我的努力都是徒劳的。

非常感谢您提前提供帮助。

Ian*_*ell 3

我怀疑有一套覆盖解决方案,但在此期间有一个图形方法:

首先,让我们将整数向量转换为边列表,以便将其制成图。我们可以用expand.grid

library(igraph)
edgelist <- do.call(rbind,lapply(x,\(x)expand.grid(x,x))) #R version >= 4.1.0
Run Code Online (Sandbox Code Playgroud)

现在我们有一个两列的 data.frame,显示所有整数(一组边)之间的连接。

igraph::graph.data.frame可以方便地由此制作图表。

从那里我们可以用来igraph::components提取连接的组件。

g <- graph.data.frame(edgelist)
split(names(components(g)$membership),components(g)$membership)
#$`1`
#[1] "1" "2" "3" "4" "5" "8"
#$`2`
#[1] "6" "9" "7"
#$`3`
#[1] "10"
#$`4`
#[1] "11"
Run Code Online (Sandbox Code Playgroud)

或者使用 Tidyverse:

library(dplyr); library(purrr)
map_dfr(x, ~expand.grid(.x,.x)) %>%
  graph.data.frame() %>%
  components() %>% 
  pluck(membership) %>%
  stack() %>%
  {split(as.numeric(as.character(.[,2])),.[,1])}

$`1`
[1] 1 2 3 4 5 8

$`2`
[1] 6 9 7

$`3`
[1] 10

$`4`
[1] 11
Run Code Online (Sandbox Code Playgroud)

  • @IanCampbell,直接转换因子变量没有给出预期的结果,因此首先将其转换为字符。:) (2认同)