如何在R中沿树的分支输出值?

时间:2018-09-02 09:58:01

标签: r tree

给定任何数据帧,如何获得一棵树或一个列表,该列表或列表告诉我R中树的每个分支的值?

例如,如果我有一个看起来像这样的数据框:

Gender      Under 18?   Student            
M           Y           Y
F           Y           Y
M           N           Y
M           Y           Y
F           N           N
M           N           N
F           N           N
F           Y           N
M           Y           N

如何像下面的树一样沿分支输出值?

沿分支具有值的树

1 个答案:

答案 0 :(得分:1)

通常,决策树是rpart或创建决策规则的其他基于树的程序包的结果。然后可以使用rpart.plot的prp或嘎嘎声的fancyRpartPlot函数对其进行绘制。

但是根据您的数据集,我创建了一个函数和一组代码(所有这些都可以放入一个大函数中)。 Igraph(或绘图仪)可用于绘制决策树。我用过Igraph。运行此程序所需的其他软件包是dplyr和tidyr。

只要您拥有与初始表一样的代码,代码就会相对灵活。因此,每行有一条完整的决策路径。

第一步创建一个函数来计算每个决策路径的出现并添加缺失的决策路径。接下来的2个步骤将创建顶点和边标签,这是在节点和顶点上创建文本所必需的。需要使用此代码中的group by语句来确保所有值最终都位于正确的位置。最后一步是创建图形,并使用边和顶点对其进行绘制。这篇文章中的图片是根据您的数据得出的结果。如果您需要像示例中那样使用不同的顶点标签,则可以执行一些ifelse语句,但这并不能使其变得灵活。图片显示基于您的示例数据的结果。

完整代码在图片下方。

enter image description here

library(tidyr)
library(dplyr)
library(igraph)

# count all the rules at the total grouped level
# add a line for each missing path with a 0
complete_df <- function(dat){

  vars <- names(dat)

  dat %>%
    group_by_all %>%
    summarise(n = n()) %>%
    ungroup %>%
    complete(!!!rlang::syms(vars), fill = list(n = 0)) ##
}

dat <- complete_df(df1)

vertex_labels <- sum(dat$n)
for(i in seq_along(dat[, -ncol(dat)])) {
  out <- dat %>%
    select(1:i, n) %>% 
    group_by_if(is.character) %>% 
    summarise(total = sum(n)) %>% 
    ungroup() %>% 
    pull(total)

  vertex_labels <- c(vertex_labels, out)
}

# labels for inside the nodes    
edge_labels <- NULL
for(i in seq_along(dat[, -ncol(dat)])) {
  out <- dat %>%
    select(1:i) %>% 
    group_by_if(is.character) %>%
    distinct %>% 
    pull(i)

  edge_labels <- c(edge_labels, out)
}

plot(graph.tree(2^(ncol(dat)) - 1, 2), 
     layout=layout_as_tree,
     edge.label = edge_labels,
     vertex.label = vertex_labels
)

数据:

df1 <- structure(list(Gender = c("M", "F", "M", "M", "F", "M", "F", "F", "M"), 
                      Under_18 = c("Y", "Y", "N", "Y", "N", "N", "N", "Y", "Y"), 
                      Student = c("Y", "Y", "Y", "Y", "N", "N", "N", "N", "N")), 
                 class = "data.frame", row.names = c(NA, -9L))