You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用R的data.tree包创建树形结构时遇类型转换错误求助

问题:基于data.frame创建树形结构时出现类型转换错误

我尝试用以下代码从data.frame生成树形结构:

library(data.tree)

# 创建数据表"mbom"
mbom <- data.frame(
  Lev. = c(1, 2, 3, 3, 2, 3, 4, 4),
  item = c("A", "B", "D", "E", "C", "F", "D", "E"),
  father = c(NA, "A", "B", "B", "A", "C", "F", "F")
)

# 创建树形结构的函数
create_tree <- function(dataframe1, node_name = "A") {
  node <- Node$new(node_name)

  subset_dataframe1 <- subset(dataframe1, father == node_name)
  if (nrow(subset_dataframe1) > 0) {
    for (i in 1:nrow(subset_dataframe1)) {
      children <- subset_dataframe1$item[i]
      node_children <- create_tree(dataframe1, children)
      node$AddChild(node_children)
    }
  }
  
  return(node)
}

# 生成树形结构
mbom_tree <- create_tree(mbom)

预期输出:

levelName
1  A
2  ¦--B
3  ¦   ¦--D
4  ¦   °--E
5  °--C
6      °--F
7          ¦--D
8          °--E

但执行代码时出现错误:

Error in as.vector(x, "character") : 
  cannot coerce type 'environment' to vector of type 'character'
Called from: as.character.default(name)

已经尝试重装data.tree包,但错误依旧。需要解决该问题,后续要扩展到数千行的多层级数据中。


错误原因

错误出在node$AddChild(node_children)这一行:AddChild方法的参数应该是节点名称(字符串),而你传入的是递归调用返回的Node对象。AddChild会自动根据传入的名称创建新节点,直接传入Node对象会触发类型转换错误。

如果要添加已创建好的Node对象,应该使用AddChildNode方法,而不是AddChild。


修正后的代码

方式一:修改递归逻辑,直接用AddChild传入节点名称

这种方式更简洁,不需要递归返回Node对象,而是在当前节点下直接创建子节点并递归处理:

library(data.tree)

mbom <- data.frame(
  Lev. = c(1, 2, 3, 3, 2, 3, 4, 4),
  item = c("A", "B", "D", "E", "C", "F", "D", "E"),
  father = c(NA, "A", "B", "B", "A", "C", "F", "F")
)

create_tree <- function(dataframe1, parent_node) {
  # 获取当前父节点的子节点数据
  subset_data <- subset(dataframe1, father == parent_node$name)
  if (nrow(subset_data) > 0) {
    for (child_name in subset_data$item) {
      # 创建子节点并添加到父节点下
      child_node <- parent_node$AddChild(child_name)
      # 递归处理子节点的子节点
      create_tree(dataframe1, child_node)
    }
  }
}

# 初始化根节点
mbom_tree <- Node$new("A")
# 递归构建树形结构
create_tree(mbom, mbom_tree)

# 打印树形结构
print(mbom_tree)

方式二:使用AddChildNode添加已创建的Node对象

如果你想保留原有的递归返回Node对象的逻辑,只需把AddChild改为AddChildNode:

library(data.tree)

mbom <- data.frame(
  Lev. = c(1, 2, 3, 3, 2, 3, 4, 4),
  item = c("A", "B", "D", "E", "C", "F", "D", "E"),
  father = c(NA, "A", "B", "B", "A", "C", "F", "F")
)

create_tree <- function(dataframe1, node_name = "A") {
  node <- Node$new(node_name)

  subset_dataframe1 <- subset(dataframe1, father == node_name)
  if (nrow(subset_dataframe1) > 0) {
    for (i in 1:nrow(subset_dataframe1)) {
      children <- subset_dataframe1$item[i]
      node_children <- create_tree(dataframe1, children)
      # 替换为AddChildNode添加已创建的节点
      node$AddChildNode(node_children)
    }
  }
  
  return(node)
}

mbom_tree <- create_tree(mbom)
print(mbom_tree)

验证结果

执行修正后的代码,会得到预期的树形输出:

levelName
1  A
2  ¦--B
3  ¦   ¦--D
4  ¦   °--E
5  °--C
6      °--F
7          ¦--D
8          °--E

两种方式都能正确构建树形结构,且可以无缝扩展到数千行的多层级数据中。

内容的提问来源于stack exchange,提问作者DuckAngel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:35:23