В ctree()
нет встроенной опции для этого. Самый простой способ сделать это «вручную» — это просто:
Изучите дерево только с Age
в качестве объясняющей переменной и maxdepth = 1
, чтобы создать только одно разделение.
Разделите данные, используя дерево из шага 1, и создайте поддерево для левой ветви.
Разделите данные, используя дерево из шага 1, и создайте поддерево для правой ветви.
Это делает то, что вы хотите (хотя обычно я бы не рекомендовал этого делать...).
Если вы используете реализацию ctree()
из partykit
, вы также можете снова объединить эти три дерева в одно дерево для визуализации, прогнозов и т. д. Это требует небольшого взлома, но все же выполнимо.
Я проиллюстрирую это с помощью данных iris
и принудительно разделю переменную Sepal.Length
, которая иначе не использовалась бы в дереве. Выучить три дерева выше легко:
library("partykit")
data("iris", package = "datasets")
tr1 <- ctree(Species ~ Sepal.Length, data = iris, maxdepth = 1)
tr2 <- ctree(Species ~ Sepal.Length + ., data = iris,
subset = predict(tr1, type = "node") == 2)
tr3 <- ctree(Species ~ Sepal.Length + ., data = iris,
subset = predict(tr1, type = "node") == 3)
Обратите внимание, однако, что важно использовать формулу с Sepal.Length + .
, чтобы убедиться, что переменные во фрейме модели упорядочены одинаково во всех деревьях.
Далее следует самый технический шаг: нам нужно извлечь необработанную структуру node
из всех трех деревьев, исправить узлы id
, чтобы они были в правильной последовательности, а затем объединить все в один узел:
fixids <- function(x, startid = 1L) {
id <- startid - 1L
new_node <- function(x) {
id <<- id + 1L
if(is.terminal(x)) return(partynode(id, info = info_node(x)))
partynode(id,
split = split_node(x),
kids = lapply(kids_node(x), new_node),
surrogates = surrogates_node(x),
info = info_node(x))
}
return(new_node(x))
}
no <- node_party(tr1)
no$kids <- list(
fixids(node_party(tr2), startid = 2L),
fixids(node_party(tr3), startid = 5L)
)
no
## [1] root
## | [2] V2 <= 5.4
## | | [3] V4 <= 1.9 *
## | | [4] V4 > 1.9 *
## | [5] V2 > 5.4
## | | [6] V4 <= 4.7
## | | | [7] V4 <= 3.6 *
## | | | [8] V4 > 3.6 *
## | | [9] V4 > 4.7
## | | | [10] V5 <= 1.7 *
## | | | [11] V5 > 1.7 *
И, наконец, мы создаем фрейм модели соединения, содержащий все данные, и объединяем его с новым деревом соединений. Добавлена некоторая информация о подогнанных узлах и ответе, чтобы иметь возможность превратить дерево в constparty
для хорошей визуализации и прогнозов. Информацию об этом см. в разделе vignette("partykit", package = "partykit")
:
d <- model.frame(Species ~ Sepal.Length + ., data = iris)
tr <- party(no,
data = d,
fitted = data.frame(
"(fitted)" = fitted_node(no, data = d),
"(response)" = model.response(d),
check.names = FALSE),
terms = terms(d),
)
tr <- as.constparty(tr)
И тогда мы закончили и можем визуализировать наше комбинированное дерево с принудительным первым разделением:
plot(tr)
person
Achim Zeileis
schedule
05.10.2016