【发布时间】:2021-10-26 14:59:06
【问题描述】:
我正在尝试基于二进制拆分创建一个边缘列表。 如果我有一个只包含节点号和其他一些指标的数据框,那么我可以手动为节点创建一个边列表。例如,如果我的数据框如下所示:
dfTest <- data.frame(
node = c(1,2,3,4,5),
var = c("milk", NA, "coffee", NA, NA),
isLeaf = c(F, T, F, T, T)
)
> dfTest
node var isLeaf
1 1 milk FALSE
2 2 <NA> TRUE
3 3 coffee FALSE
4 4 <NA> TRUE
5 5 <NA> TRUE
然后,基于var 或isLeaf 列,我可以手动创建一个边列表来连接节点。例如,由于节点 2 是叶节点,我知道节点 1 必须转到节点 2。然后(因为它们是二元拆分)我知道节点 1 也必须连接到节点 3。由于节点 4 和 5 是叶节点,我知道他们必须在节点 3 上拆分。
手动创建边缘列表如下所示:
edges <- data.frame(
from = c(1, 1, 3, 3),
to = c(2, 3, 4, 5)
)
to 列很容易找到...它始终是c(2:length(dfTest$nodes))。在这种情况下2,3,4,5。但事实证明,from 专栏很难找到。
只是为了视觉帮助,生成的树看起来像这样:
有什么方法可以做到这一点而无需手动计算边缘?
编辑: 作为对答案的回应,我添加了一个稍大的数据集以供使用:
dfTest <- data.frame(
node = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
var = c("milk", "milk", NA, NA, "coffee", "sugar", NA, NA, "milk", NA, NA),
isLeaf = c(F, F, T, T, F, F, T, T, F, T, T)
)
一点解释:
从var 列我知道牛奶(根/节点1)分裂成另一个牛奶(节点2)。然后我可以看到节点 2 拆分为 NA(节点 3)和 NA(节点 4)。我知道它们是二进制拆分,我知道节点 2 不能再拆分。所以,我必须回到上一个只有 1 个拆分的节点……在这种情况下,节点 1(即牛奶)然后在咖啡上向右拆分(节点 5)。同样,由于它们是二元拆分,我现在知道咖啡(节点 5)必须拆分为糖(节点 6)。 Sugar(节点 6)后跟 2 个 NA(节点 7 和 8)。现在,我必须回到咖啡(节点 5)并向右拆分以获取牛奶(节点 9),牛奶拆分为 2 个 NA(节点 10 和 11)
所需的节点/边缘列表应如下所示:
edges <- data.frame(
from = c(1,2,2,1,5,6,6,5,9,9),
to = c(2,3,4,5,6,7,8,9,10,11)
)
【问题讨论】:
-
dfTest中的节点是否按拓扑顺序排列?
-
老实说,我现在正在谷歌搜索图的拓扑排序。我以前没有听说过这个词。所以,我不确定
-
我的意思是从您的数据中,如果您交换数据中节点 1 和 3 的行,您会得到不同的图表。所以为了得到一个特定的图,我们需要假设 dfTest 中的节点有一些排序
-
你说得对,如果我们交换节点 1 和 3,我们会得到不同的图表。所以(根据我有限和简短的理解)我会说,是的,dfTest 中的节点是拓扑顺序的
-
您无法以更好的格式获取数据?如果我得到这样的数据,我会很生气。也就是说,仅使用这些数据,您就可以根据 isLeaf 值的运行计数创建组(
rleid很有用),但我不确定这是否会扩展到更大的数据集。树需要变得更大/更深多少?