如何使用路径爬升 rpart 对象的树结构以手动清除某些节点?
How to climb the tree structure of rpart object using path in order to purge manually some nodes?
我正在使用 rpart 构建分类树。我想根据叶节点上的一些标准开发自己的修剪功能。
例如,如果一个叶节点不符合某些标准(在我的情况下参数估计的稳定性),我想爬进树结构并获得该叶节点的父节点(即使该节点不是终端节点) .
为此,我想使用路径遍历树,我需要获取叶节点及其父节点,以便在必要时爬树。
我们来看这个例子:
fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis)
> fit
n= 81
node), split, n, loss, yval, (yprob)
* denotes terminal node
1) root 81 17 absent (0.79012346 0.20987654)
2) Start>=8.5 62 6 absent (0.90322581 0.09677419)
4) Start>=14.5 29 0 absent (1.00000000 0.00000000) *
5) Start< 14.5 33 6 absent (0.81818182 0.18181818)
10) Age< 55 12 0 absent (1.00000000 0.00000000) *
11) Age>=55 21 6 absent (0.71428571 0.28571429)
22) Age>=111 14 2 absent (0.85714286 0.14285714) *
23) Age< 111 7 3 present (0.42857143 0.57142857) *
3) Start< 8.5 19 8 present (0.42105263 0.57894737) *
使用 fit$frame 我可以获得有关叶节点的信息:
fit$frame
var n wt dev yval complexity ncompete nsurrogate yval2.V1 yval2.V2 yval2.V3 yval2.V4 yval2.V5
1 Start 81 81 17 1 0.17647059 2 1 1.00000000 64.00000000 17.00000000 0.79012346 0.20987654
2 Start 62 62 6 1 0.01960784 2 2 1.00000000 56.00000000 6.00000000 0.90322581 0.09677419
4 <leaf> 29 29 0 1 0.01000000 0 0 1.00000000 29.00000000 0.00000000 1.00000000 0.00000000
5 Age 33 33 6 1 0.01960784 2 2 1.00000000 27.00000000 6.00000000 0.81818182 0.18181818
10 <leaf> 12 12 0 1 0.01000000 0 0 1.00000000 12.00000000 0.00000000 1.00000000 0.00000000
11 Age 21 21 6 1 0.01960784 2 0 1.00000000 15.00000000 6.00000000 0.71428571 0.28571429
22 <leaf> 14 14 2 1 0.01000000 0 0 1.00000000 12.00000000 2.00000000 0.85714286 0.14285714
23 <leaf> 7 7 3 2 0.01000000 0 0 2.00000000 3.00000000 4.00000000 0.42857143 0.57142857
3 <leaf> 19 19 8 2 0.01000000 0 0 2.00000000 8.00000000 11.00000000 0.42105263 0.57894737
我可以得到数据中行的对应关系 table 使用它所在的相应叶节点:fit$where
现在我还想获得叶节点的父节点。我知道 path.rpart 为我提供了为获得叶节点而完成的所有拆分。例如对于叶节点 23:
> path.rpart(fit, 23)
node number: 23
root
Start>=8.5
Start< 14.5
Age>=55
Age< 111
我要获取的是23号节点的父节点号的路径?我怎样才能做这个关联?
提前致谢。
您不需要关于树的任何信息,因为所有节点都具有相同的模式。让我们拟合一棵更有趣的树:
(fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis,
cp = .0001, minsplit = 5))
# n= 81
#
# node), split, n, loss, yval, (yprob)
# * denotes terminal node
#
# 1) root 81 17 absent (0.79012346 0.20987654)
# 2) Start>=8.5 62 6 absent (0.90322581 0.09677419)
# 4) Start>=14.5 29 0 absent (1.00000000 0.00000000) *
# 5) Start< 14.5 33 6 absent (0.81818182 0.18181818)
# 10) Age< 55 12 0 absent (1.00000000 0.00000000) *
# 11) Age>=55 21 6 absent (0.71428571 0.28571429)
# 22) Age>=98 16 2 absent (0.87500000 0.12500000) *
# 23) Age< 98 5 1 present (0.20000000 0.80000000) *
# 3) Start< 8.5 19 8 present (0.42105263 0.57894737)
# 6) Age< 11.5 2 0 absent (1.00000000 0.00000000) *
# 7) Age>=11.5 17 6 present (0.35294118 0.64705882)
# 14) Start< 5.5 12 6 absent (0.50000000 0.50000000)
# 28) Age>=130.5 2 0 absent (1.00000000 0.00000000) *
# 29) Age< 130.5 10 4 present (0.40000000 0.60000000)
# 58) Age< 93 6 2 absent (0.66666667 0.33333333)
# 116) Number< 4.5 3 0 absent (1.00000000 0.00000000) *
# 117) Number>=4.5 3 1 present (0.33333333 0.66666667) *
# 59) Age>=93 4 0 present (0.00000000 1.00000000) *
# 15) Start>=5.5 5 0 present (0.00000000 1.00000000) *
如果可能,每个节点将一分为二并编号为 node * 2 + 0:1
,因此如果您有一个编号为 5 的节点,其子节点将为 5 * 2 + 0:1
。另请注意,使用此模式,偶数编号的节点将不会有子节点。
因此,给定任何节点号,我们可以回头找到父节点:
parent(23)
# [1] 1 2 5 11 23
## children of the same node should have the same path
identical(head(parent(28), -1), head(parent(29), -1))
# [1] TRUE
parent <- function(x) {
if (x[1] != 1)
c(Recall(if (x %% 2 == 0L) x / 2 else (x - 1) / 2), x) else x
}
我正在使用 rpart 构建分类树。我想根据叶节点上的一些标准开发自己的修剪功能。 例如,如果一个叶节点不符合某些标准(在我的情况下参数估计的稳定性),我想爬进树结构并获得该叶节点的父节点(即使该节点不是终端节点) . 为此,我想使用路径遍历树,我需要获取叶节点及其父节点,以便在必要时爬树。
我们来看这个例子:
fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis)
> fit
n= 81
node), split, n, loss, yval, (yprob)
* denotes terminal node
1) root 81 17 absent (0.79012346 0.20987654)
2) Start>=8.5 62 6 absent (0.90322581 0.09677419)
4) Start>=14.5 29 0 absent (1.00000000 0.00000000) *
5) Start< 14.5 33 6 absent (0.81818182 0.18181818)
10) Age< 55 12 0 absent (1.00000000 0.00000000) *
11) Age>=55 21 6 absent (0.71428571 0.28571429)
22) Age>=111 14 2 absent (0.85714286 0.14285714) *
23) Age< 111 7 3 present (0.42857143 0.57142857) *
3) Start< 8.5 19 8 present (0.42105263 0.57894737) *
使用 fit$frame 我可以获得有关叶节点的信息:
fit$frame
var n wt dev yval complexity ncompete nsurrogate yval2.V1 yval2.V2 yval2.V3 yval2.V4 yval2.V5
1 Start 81 81 17 1 0.17647059 2 1 1.00000000 64.00000000 17.00000000 0.79012346 0.20987654
2 Start 62 62 6 1 0.01960784 2 2 1.00000000 56.00000000 6.00000000 0.90322581 0.09677419
4 <leaf> 29 29 0 1 0.01000000 0 0 1.00000000 29.00000000 0.00000000 1.00000000 0.00000000
5 Age 33 33 6 1 0.01960784 2 2 1.00000000 27.00000000 6.00000000 0.81818182 0.18181818
10 <leaf> 12 12 0 1 0.01000000 0 0 1.00000000 12.00000000 0.00000000 1.00000000 0.00000000
11 Age 21 21 6 1 0.01960784 2 0 1.00000000 15.00000000 6.00000000 0.71428571 0.28571429
22 <leaf> 14 14 2 1 0.01000000 0 0 1.00000000 12.00000000 2.00000000 0.85714286 0.14285714
23 <leaf> 7 7 3 2 0.01000000 0 0 2.00000000 3.00000000 4.00000000 0.42857143 0.57142857
3 <leaf> 19 19 8 2 0.01000000 0 0 2.00000000 8.00000000 11.00000000 0.42105263 0.57894737
我可以得到数据中行的对应关系 table 使用它所在的相应叶节点:fit$where
现在我还想获得叶节点的父节点。我知道 path.rpart 为我提供了为获得叶节点而完成的所有拆分。例如对于叶节点 23:
> path.rpart(fit, 23)
node number: 23
root
Start>=8.5
Start< 14.5
Age>=55
Age< 111
我要获取的是23号节点的父节点号的路径?我怎样才能做这个关联?
提前致谢。
您不需要关于树的任何信息,因为所有节点都具有相同的模式。让我们拟合一棵更有趣的树:
(fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis,
cp = .0001, minsplit = 5))
# n= 81
#
# node), split, n, loss, yval, (yprob)
# * denotes terminal node
#
# 1) root 81 17 absent (0.79012346 0.20987654)
# 2) Start>=8.5 62 6 absent (0.90322581 0.09677419)
# 4) Start>=14.5 29 0 absent (1.00000000 0.00000000) *
# 5) Start< 14.5 33 6 absent (0.81818182 0.18181818)
# 10) Age< 55 12 0 absent (1.00000000 0.00000000) *
# 11) Age>=55 21 6 absent (0.71428571 0.28571429)
# 22) Age>=98 16 2 absent (0.87500000 0.12500000) *
# 23) Age< 98 5 1 present (0.20000000 0.80000000) *
# 3) Start< 8.5 19 8 present (0.42105263 0.57894737)
# 6) Age< 11.5 2 0 absent (1.00000000 0.00000000) *
# 7) Age>=11.5 17 6 present (0.35294118 0.64705882)
# 14) Start< 5.5 12 6 absent (0.50000000 0.50000000)
# 28) Age>=130.5 2 0 absent (1.00000000 0.00000000) *
# 29) Age< 130.5 10 4 present (0.40000000 0.60000000)
# 58) Age< 93 6 2 absent (0.66666667 0.33333333)
# 116) Number< 4.5 3 0 absent (1.00000000 0.00000000) *
# 117) Number>=4.5 3 1 present (0.33333333 0.66666667) *
# 59) Age>=93 4 0 present (0.00000000 1.00000000) *
# 15) Start>=5.5 5 0 present (0.00000000 1.00000000) *
如果可能,每个节点将一分为二并编号为 node * 2 + 0:1
,因此如果您有一个编号为 5 的节点,其子节点将为 5 * 2 + 0:1
。另请注意,使用此模式,偶数编号的节点将不会有子节点。
因此,给定任何节点号,我们可以回头找到父节点:
parent(23)
# [1] 1 2 5 11 23
## children of the same node should have the same path
identical(head(parent(28), -1), head(parent(29), -1))
# [1] TRUE
parent <- function(x) {
if (x[1] != 1)
c(Recall(if (x %% 2 == 0L) x / 2 else (x - 1) / 2), x) else x
}