partykit:在叶节点箱线图上显示叶节点百分位数值

6
我正在尝试使用partykit绘制由rpart生成的回归树。假设使用的公式为y ~ x1 + x2 + x3 +...+ xn。我想要实现的是,终端节点上有箱线图,并在顶部列出分配给每个节点的观测值y的分布的第10、50和90个百分位数的标签,即,在表示每个终端节点的箱线图上方,我想显示一个标签,如“第10百分位数=$200,平均值=$247,第90百分位数=$292。”
下面的代码生成所需的树:
library("rpart")
fit <- rpart(Price ~ Mileage + Type + Country, cu.summary)
library("partykit")
tree.2 <- as.party(fit)

以下代码生成了终端图,但是终端节点上没有期望的标签:
plot(tree.2, type = "simple", terminal_panel = node_boxplot(tree.2,
  col = "black", fill = "lightgray", width = 0.5, yscale = NULL,
  ylines = 3, cex = 0.5, id = TRUE))

如果我能显示节点的平均y值,那么很容易就可以用百分位数来增强标签,因此我的第一步是仅在每个终端节点上方显示其平均y值。
我知道可以使用以下代码检索节点(此处为节点#12)内的平均y值:
colMeans(tree.2[12]$fitted[2])

我尝试创建一个公式,并使用boxplot面板生成函数的 mainlab 参数来生成包含此平均值的标签:

labf <- function(node) colMeans(node$fitted[2])
plot(tree.2, type = "simple", terminal_panel = node_boxplot(tree.2,
  col = "black", fill = "lightgray", width = 0.5, yscale = NULL,
  ylines = 3, cex = 0.5, id = TRUE, mainlab = tf))

很遗憾,这会生成错误消息:

Error in mainlab(names(obj)[nid], sum(wn)) : unused argument (sum(wn)).

但是看起来这是正确的方法,因为如果我使用:
plot(tree.2, type = "simple", terminal_panel = node_boxplot(tree.2,
  col = "black", fill = "lightgray", width = 0.5, yscale = NULL,
  ylines = 3, cex = 0.5, id = TRUE, mainlab = colMeans(tree.2$fitted[2])))

然后我在根节点处显示了正确的平均y值。我希望能帮助修复上述错误,以便我可以显示每个单独终端节点的平均y值。从那里开始,添加其他百分位数并使格式变得漂亮应该很容易。


你能否尝试制作一个可重现的问题版本?然后我会尝试查看它。 - Achim Zeileis
当然。谢谢@AchimZeileis!下面的代码使用了RPART附带的cu Consumer Reports数据集。 fit <- rpart(Price ~ Mileage + Type + Country, cu.summary)par(xpd = TRUE)plot(fit, compress = TRUE)text(fit, use.n = TRUE)tree.2<-as.party(fit)plot(tree.2)这将生成一个带有终端节点箱线图的树状图。我想要做的是在每个终端节点上方放置平均值(以及稍后的其他百分位数)标签。因此,左侧的终端节点的标签将显示为“mean = 7629.048”,而不是“Node 4(n=21)”。 - djr99
1个回答

4

原则上,您正在正确的轨道上。但是如果mainlab应该是一个函数,则它不是node的函数,而是idnobs的函数,请参阅?node_boxplot。此外,您可以使用整个树的fitted数据更容易地为所有叶节点计算平均值(或某些分位数)的表格:

tab <- tapply(tree.2$fitted[["(response)"]],
  factor(tree.2$fitted[["(fitted)"]], levels = 1:length(tree.2)),
  FUN = mean)

然后你可以通过四舍五入/格式化来准备绘图:
tab <- format(round(tab, digits = 3))
tab
##           1           2           3           4           5           6 
## "       NA" "       NA" "       NA" " 7629.048" "       NA" "12241.552" 
##           7           8           9          10          11          12 
## "14846.895" "22317.727" "       NA" "       NA" "17607.444" "21499.714" 
##          13 
## "27646.000" 

如果你想将其添加到显示中,可以编写自己的帮助函数来处理 mainlab:

mlab <- function(id, nobs) paste("Mean =", tab[id])
plot(tree.2, tp_args = list(mainlab = mlab))

enter image description here


谢谢@AchimZeileis!这解决了我的问题,我能够扩展你提供的示例以包括百分位数。我非常感谢您的帮助和详细的示例代码。是否有任何方法可以通过ep_args参数类似地修改边缘的标签(例如用换行符替换逗号)?我发现了一个“split”参数,但没有看到它的影响。只设置justmin=3可以防止边缘标签重叠,但它们仍然很长。此外,“nobs”是什么?观察数量吗?我似乎找不到有关该参数的详细信息。再次感谢! - djr99
目前不支持换行符,必须自己修改 edge_simple 的版本。在下一个版本的 partykit 中,我会考虑这个问题。至于 nobs:它代表“观测数量”,就像 ?nobs 提取函数中所示。这个应该更好地记录下来。 - Achim Zeileis
再次感谢!我发现partykit非常有用。 - djr99
很好,如果对您有用我很高兴。如果它解决了原始问题,请也接受答案。 - Achim Zeileis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接