这个问题已经被问过几次了,但它们都是用不同的语言(例如,见here for javahere for python,但我试图用R实现这个目标.

我有一棵树.我的树按照深度优先左侧遍历排序,如下代码所示:

df <- data.frame(
  var = c("x2", NA, NA, "x1", NA, "x2", "x2", NA, NA, NA, "x2", NA, "x10", NA, NA, NA, "x1", NA, NA, "x5", NA, NA),
  node = c(1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 1, 1, 2, 3, 1, 2, 3),
  terminal = c(FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE),
  iteration = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2),
  treeNum = c(1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 2, 2, 2, 3, 3, 3),
  stringsAsFactors = FALSE 
)

该办公室的 struct 如下:

var =变量名(如果是终端 node 或stump,则这只是NA)

node = node 编号

终端=是否是终端 node .

迭代=迭代次数

树号=树号

正如你所看到的,我的rabrame包含了2次迭代的3棵树.

为了清楚起见,如果我们看一棵树(例如,迭代1中的树号为2),它看起来像下面的图像(其中 node 按照遍历方法编号):

binary tree

此树的深度(按深度优先的左侧方法排序)将为:0,1,1,2,3,3,2

最终,我想做一个depth列添加到我的框架,但我努力使代码工作.有什么建议我怎么做吗?

推荐答案

我想如果你明确地知道哪些 node 是终端,哪些不是,那么就可以解码.这里有一个函数可以用额外的信息来计算深度

node_depth <- function(tree) {
  stopifnot(is.data.frame(tree))
  stopifnot("terminal" %in% names(tree))
  depths <- rep(0, nrow(tree))
  recurse <- function(idx, current_depth) {
    if (idx > nrow(tree)) {
      return(idx)
    }
    depths[idx] <<- current_depth
    if (tree$terminal[idx]) {
      return(idx+1)
    }
    step <- recurse(idx+1, current_depth + 1)
    step <- recurse(step, current_depth + 1)
    step
  }
  recurse(1, 1)
  depths
}

它看起来像你画的树在迭代== 1时是treeupt == 2.我们可以在树上运行函数,

node_depth(subset(df, iteration==1 & treeNum==2))
# [1] 1 2 2 3 4 4 3

(如果你喜欢从0开始,你可以从向量中减go 1).

我们可以在所有的树上运行这个,

lapply(split(df, ~treeNum + iteration), 
  function(x) cbind(x, depth=node_depth(x)))

它会返回

$`1.1`
   var node terminal iteration treeNum depth
1   x2    1    FALSE         1       1     1
2 <NA>    2     TRUE         1       1     2
3 <NA>    3     TRUE         1       1     2

$`2.1`
    var node terminal iteration treeNum depth
4    x1    1    FALSE         1       2     1
5  <NA>    2     TRUE         1       2     2
6    x2    3    FALSE         1       2     2
7    x2    4    FALSE         1       2     3
8  <NA>    5     TRUE         1       2     4
9  <NA>    6     TRUE         1       2     4
10 <NA>    7     TRUE         1       2     3

$`3.1`
    var node terminal iteration treeNum depth
11   x2    1    FALSE         1       3     1
12 <NA>    2     TRUE         1       3     2
13  x10    3    FALSE         1       3     2
14 <NA>    4     TRUE         1       3     3
15 <NA>    5     TRUE         1       3     3

$`1.2`
    var node terminal iteration treeNum depth
16 <NA>    1     TRUE         2       1     1

$`2.2`
    var node terminal iteration treeNum depth
17   x1    1    FALSE         2       2     1
18 <NA>    2     TRUE         2       2     2
19 <NA>    3     TRUE         2       2     2

$`3.2`
    var node terminal iteration treeNum depth
20   x5    1    FALSE         2       3     1
21 <NA>    2     TRUE         2       3     2
22 <NA>    3     TRUE         2       3     2

因此,虽然深度优先的前序遍历通常不能允许您重建树,但如果您明确知道哪些 node 是终端 node ,哪些不是终端 node ,则可以.

R相关问答推荐

使用Shiny组合和显示复制和粘贴的数据

R:连接值,而不是变量?

随机森林回归:下拉列重要性

如果行和大于值,则过滤

手动打印线型gplot

如何在emmeans中计算连续变量的对比度

通过在colname中查找其相应值来创建列

R Select()可以测试不存在的子集列

绘制采样开始和采样结束之间的事件

合并后返回列表的数据帧列表

如何根据R中其他变量的类别汇总值?

KM估计的差异:SvyKm与带权重的调查

将多个变量组合成宽格式

如何将一个方阵分解成没有循环的立方体

在R中,如何从一系列具有索引名的变量快速创建数据帧?

有没有办法定制Plot(allEffects())面板标题?

R -基线图-图形周围的阴影区域

计算Mean by分组和绑定到R中的数据集

将数据从一列转换为按组累计计数的单个虚拟变量

是什么打破了此Quarto仪表板中的工具提示?