使用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
相关产品推荐
相关产品推荐

