【问题标题】:Find root nodes in a hierarchical data.frame在分层 data.frame 中查找根节点
【发布时间】:2021-12-01 02:50:37
【问题描述】:

我有一个 data.frame 为我提供它的行的分层信息 (DF_in):

   id parent_id
1   1        NA
2   2        NA
3   3         1
4   4         2
5   5         3
6   6         4
7   7         1
8   8         2
9   9         3
10 10         4

我想查找每一行的 root_id (DF_out):

   id parent_id root_id
1   1        NA      NA
2   2        NA      NA
3   3         1       1
4   4         2       2
5   5         3       1
6   6         4       2
7   7         1       1
8   8         2       2
9   9         3       1
10 10         4       2

通常我更喜欢使用data.table,但这似乎需要递归解决方案,我不知道如何有效地解决这个问题。

DF_in <- data.frame(id = 1:10, parent_id = c(NA, NA, 1:4, 1:4))
# library(data.table)
# setDT(DF_in)

DF_out <- data.frame(id = 1:10, parent_id = c(NA, NA, 1:4, 1:4), root_id = c(NA, NA, rep(1:2, 4)))

【问题讨论】:

  • 你应该看看包igraph
  • 感谢您的提示!你有什么具体的功能吗?

标签: r data.table


【解决方案1】:

快点:

find_root <- function(id, table) {
  par <- table[match(id, table$id), 'parent_id']
  if (is.na(par)) id else find_root(id = par, table)
}

DF_in$root_id <- vapply(DF_in$id, \(x) find_root(x, DF_in), integer(1L))


> DF_in
   id parent_id root_id
1   1        NA       1
2   2        NA       2
3   3         1       1
4   4         2       2
5   5         3       1
6   6         4       2
7   7         1       1
8   8         2       2
9   9         3       1
10 10         4       2

【讨论】:

    【解决方案2】:

    这是另一个使用dplyr 的解决方案。当然,如果需要多次运行这段代码,你可以把它变成一个函数。

    library(dplyr)
    #> 
    #> Attache Paket: 'dplyr'
    #> The following objects are masked from 'package:stats':
    #> 
    #>     filter, lag
    #> The following objects are masked from 'package:base':
    #> 
    #>     intersect, setdiff, setequal, union
    
    id <- c(1:10)
    
    parent_id <- c(NA, NA, 1, 2, 3, 4, 1, 2, 3, 4)
    
    df <- tibble(id = id, parent_id = parent_id)
    
    df %>%
      mutate(
        root_id = pull(
          left_join(
            x = df,
            y = df,
            by = c("parent_id" = "id")),
          "parent_id.y"),
        root_id = ifelse(
          test = is.na(root_id) & !is.na(parent_id),
          yes = parent_id,
          no = root_id
        )
      )
    #> # A tibble: 10 x 3
    #>       id parent_id root_id
    #>    <int>     <dbl>   <dbl>
    #>  1     1        NA      NA
    #>  2     2        NA      NA
    #>  3     3         1       1
    #>  4     4         2       2
    #>  5     5         3       1
    #>  6     6         4       2
    #>  7     7         1       1
    #>  8     8         2       2
    #>  9     9         3       1
    #> 10    10         4       2
    

    reprex package 创建于 2021-10-12 (v2.0.1)

    【讨论】:

      猜你喜欢
      • 2020-05-06
      • 2015-04-28
      • 2013-12-31
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-22
      • 1970-01-01
      相关资源
      最近更新 更多