martin-borkovec / ggparty

147 stars 14 forks source link

Can't get past this error #37

Closed wordsmith189 closed 4 years ago

wordsmith189 commented 4 years ago

Would you have an idea of how I can get past this error? Here's a reprex

library(rio)
library(party)
#> Loading required package: grid
#> Loading required package: mvtnorm
#> Loading required package: modeltools
#> Loading required package: stats4
#> Loading required package: strucchange
#> Loading required package: zoo
#> 
#> Attaching package: 'zoo'
#> The following objects are masked from 'package:base':
#> 
#>     as.Date, as.Date.numeric
#> Loading required package: sandwich
library(tidyverse)
library(ggparty)
#> Loading required package: partykit
#> Loading required package: libcoin
#> 
#> Attaching package: 'partykit'
#> The following objects are masked from 'package:party':
#> 
#>     cforest, ctree, ctree_control, edge_simple, mob, mob_control,
#>     node_barplot, node_bivplot, node_boxplot, node_inner, node_surv,
#>     node_terminal, varimp

my_DV <- runif(20, min=-3, max=3)
gender <- sample(1:2, 20, replace=T) %>% 
  as.factor() %>% recode("1" = "f", "2" = "m")
age <- sample(26:51, 20, replace=T)
duration <- runif(20)
dat <- data.frame(my_DV, gender, age, duration)

m1.tree <- ctree(my_DV ~
                   gender +
                   age +
                   duration,
                 data = dat)

ggparty(m1.tree)
#> Error in `[<-.data.frame`(`*tmp*`, i_id, "y", value = NA_real_): missing values are not allowed in subscripted assignments of data frames
#> WHEN RUN IN CONSOLE/OUTSIDE OF THE REPREX THE ERROR READS AS
#> Error in UseMethod("depth") : 
#  no applicable method for 'depth' applied to an object of class 
# "c('BinaryTree', 'BinaryTreePartition')"

Created on 2020-03-04 by the reprex package (v0.3.0)

martin-borkovec commented 4 years ago

the problem seems to be, that the tree doesn't contain any inner nodes (i.e. isn't really a tree...) you can always use plot() to get a basic visualization.

library(tidyverse)
#> Warning: package 'tidyverse' was built under R version 3.6.2
#> Warning: package 'purrr' was built under R version 3.6.2
library(ggparty)
#> Loading required package: partykit
#> Loading required package: grid
#> Loading required package: libcoin
#> Loading required package: mvtnorm

my_DV <- runif(20, min=-3, max=3)
gender <- sample(1:2, 20, replace=T) %>% 
  as.factor() %>% recode("1" = "f", "2" = "m")
age <- sample(26:51, 20, replace=T)
duration <- runif(20)
dat <- data.frame(my_DV, gender, age, duration)

m1.tree <- ctree(my_DV ~
                   gender +
                   age +
                   duration,
                 data = dat)

m1.tree
#> 
#> Model formula:
#> my_DV ~ gender + age + duration
#> 
#> Fitted party:
#> [1] root: -0.649 (n = 20, err = 57.4) 
#> 
#> Number of inner nodes:    0
#> Number of terminal nodes: 1
plot(m1.tree)

Created on 2020-03-04 by the reprex package (v0.3.0)

I haven't really anticipated such a case. ggparty should at least throw a meaningful error message... or what behaviour would you expect?

wordsmith189 commented 4 years ago

Oh OK - I guess I didn't get enough data into the reprex... My actual dataset has 14,000 rows, and there's enough going on in the tree... But still I always get the error no applicable method for 'depth' applied to an object of class

"c('BinaryTree', 'BinaryTreePartition')"

Many thanks for addressing this!!

wordsmith189 commented 4 years ago

sorry - I did not mean to necessarily close the issue :-(

martin-borkovec commented 4 years ago

So I think the problem stems from the fact, that both "partykit" and "party" contain a ctree() function that each behaves slightly different (class of output is different and arguments can differ slightly i.e. controls vs. control). I assume that you used the "party" version, that's why your tree object can not be handled with ggparty. check out the code below... I know, once again, a proper error message would have been helpful, sorry about that.

library(ggparty)
#> Loading required package: ggplot2
#> Loading required package: partykit
#> Loading required package: grid
#> Loading required package: libcoin
#> Loading required package: mvtnorm

airq <- subset(airquality, !is.na(Ozone))

airct_party <- party::ctree(Ozone ~ ., data = airq, controls = party::ctree_control(maxsurrogate = 3))
class(airct_party)
#> [1] "BinaryTree"
#> attr(,"package")
#> [1] "party"
ggparty(airct_party)
#> Error in UseMethod("depth"): no applicable method for 'depth' applied to an object of class "c('BinaryTree', 'BinaryTreePartition')"

airct_partykit <- partykit::ctree(Ozone ~ ., data = airq, control = partykit::ctree_control(maxsurrogate = 3))
class(airct_partykit)
#> [1] "constparty" "party"

ggparty(airct_partykit) + 
  geom_edge() + 
  geom_edge_label() +
  geom_node_splitvar()

Created on 2020-03-08 by the reprex package (v0.3.0)

Nevertheless, ggparty seems to have trouble with the terminal nodes. I will look into that and get back to you. Thanks a lot for using the package and posting the issues, I will do my best to address them!

wordsmith189 commented 4 years ago

Wonderful. Thank you. And yes - I was using party, so I'll try partykit instead.

martin-borkovec commented 4 years ago

Actually, the only thing that's having trouble is the autoplot function, as far as I can tell. I will try to address it in the next update.

However, the design of the generic plot function can be reproduced fairly easily.

library(ggparty)
#> Loading required package: ggplot2
#> Loading required package: partykit
#> Loading required package: grid
#> Loading required package: libcoin
#> Loading required package: mvtnorm

airq <- subset(airquality, !is.na(Ozone))
airct_partykit <- partykit::ctree(Ozone ~ ., data = airq, control = partykit::ctree_control(maxsurrogate = 3))

autoplot(airct_partykit)


plot(airct_partykit)


ggparty(airct_partykit) + 
  geom_edge() + 
  geom_edge_label() +
  geom_node_splitvar() +
  geom_node_label(aes(label = paste0("Node ", id, ", N = ", nodesize)),
                  ids = "terminal") +
  geom_node_plot(gglist = list(geom_boxplot(aes(y = Ozone, x = "" )),
                               xlab("")),
                 nudge_y = -0.03)

Created on 2020-03-11 by the reprex package (v0.3.0)