是否有一种干净的 dplyr 方式来执行多个左(自)连接?

Cor*_*ldH 7 r dplyr

我有以下工作代码:

test_hierarchie <- tribble(~child, ~parent,
                "A", "B",
                "B", "C",
                "D", "E"
                )

test_hierarchie_transformed <- test_hierarchie %>%
    left_join(test_hierarchie, by = c("parent" = "child"), suffix = c("", "_grant")) %>%
    left_join(test_hierarchie, by = c("parent_grant" = "child"), suffix = c("", "_grant")) %>%
    left_join(test_hierarchie, by = c("parent_grant_grant" = "child"), suffix = c("", "_grant")) %>%
    left_join(test_hierarchie, by = c("parent_grant_grant_grant" = "child"), suffix = c("", "_grant")) %>%
    left_join(test_hierarchie, by = c("parent_grant_grant_grant_grant" = "child"), suffix = c("", "_grant")) %>%
    pivot_longer(names_to = "relation", cols = contains("parent"), values_to = "parent") %>%
    filter(!is.na(parent))
Run Code Online (Sandbox Code Playgroud)

结果:

# A tibble: 4 x 3
  child relation     parent
  <chr> <chr>        <chr> 
1 A     parent       B     
2 A     parent_grant C     
3 B     parent       C     
4 D     parent       E 
Run Code Online (Sandbox Code Playgroud)

这是期望的结果,存在大量的 left_join,因为我对于真实数据不确定最大层次结构是什么。

我的问题是:有没有办法做到更简洁、更有活力?谢谢!

编辑 1:是的,我的意思是“盛大”而不是“授予”,哈哈 编辑 2:很好的解决方案,正是我正在寻找的!感谢大家的参与,前几天我正在考虑另一个项目,iGraph 似乎对此非常有帮助。

ste*_*fan 2

按照 @zx8754 的建议,实现所需结果的一种选择是left_joins通过递归函数执行此操作,该函数在没有更多匹配项时停止:

\n
library(dplyr)\nlibrary(tidyr)\n\ntest_hierarchie <- tribble(\n  ~child, ~parent,\n  "A", "B",\n  "B", "C",\n  "D", "E"\n)\n\nleft_join_recursive <- function(x, by) {\n  x <- left_join(x, test_hierarchie, by = setNames("child", by), suffix = c("", "_grant"))\n  byby <- paste0(by, "_grant")\n  if (!all(is.na(x[[byby]]))) {\n    left_join_recursive(x, byby)  \n  } else {\n    x\n  }\n}\n\ntest_hierarchie_transformed <- left_join_recursive(test_hierarchie, "parent") %>%\n  pivot_longer(names_to = "relation", cols = contains("parent"), values_to = "parent") %>%\n  filter(!is.na(parent))\n\ntest_hierarchie_transformed\n#> # A tibble: 4 \xc3\x97 3\n#>   child relation     parent\n#>   <chr> <chr>        <chr> \n#> 1 A     parent       B     \n#> 2 A     parent_grant C     \n#> 3 B     parent       C     \n#> 4 D     parent       E\n
Run Code Online (Sandbox Code Playgroud)\n

为了检查该方法是否适用于更一般的情况,我在示例数据中添加了另一行:

\n
test_hierarchie <- add_row(test_hierarchie, child = "C", parent = "D")\n\ntest_hierarchie_transformed <- left_join_recursive(test_hierarchie, "parent") %>%\n  pivot_longer(names_to = "relation", cols = contains("parent"), values_to = "parent") %>%\n  filter(!is.na(parent))\n\ntest_hierarchie_transformed\n#> # A tibble: 10 \xc3\x97 3\n#>    child relation                 parent\n#>    <chr> <chr>                    <chr> \n#>  1 A     parent                   B     \n#>  2 A     parent_grant             C     \n#>  3 A     parent_grant_grant       D     \n#>  4 A     parent_grant_grant_grant E     \n#>  5 B     parent                   C     \n#>  6 B     parent_grant             D     \n#>  7 B     parent_grant_grant       E     \n#>  8 D     parent                   E     \n#>  9 C     parent                   D     \n#> 10 C     parent_grant             E\n
Run Code Online (Sandbox Code Playgroud)\n