martin-borkovec / ggparty

147 stars 14 forks source link

Plot coefficients (log-abilities) from `pltree` and `bttree` #40

Closed kauedesousa closed 4 years ago

kauedesousa commented 4 years ago

Hi, I am using your pkg to plot pltree and bttree objects. Plackett-Luce and Bradley-Terry models applies partykit to create the trees. But the elements in their outputs are more nested than usual. I was trying to plot the log-abilities from these models but I couldn't. I made a workaround using patchwork, but I am wondering if there is an implementation for such objects. There is?

Here a reproducible example of the desired output in the workaround using patchwork

library("PlackettLuce")
library("ggparty")
library("patchwork")

example("beans", "PlackettLuce")

nr <- nrow(beans)

# rankings into grouped rankings
G <- group(R, index = rep(1:nr, 4))

# cbind data
dat <- cbind(G, beans)

# fit PlackettLuce tree
plt <- pltree(G ~ maxTN, data = dat)

# get the coefficients
coeff <- as.vector(coef(plt, log = FALSE))
items <- rep(dimnames(coef(plt))[[2]], each = dim(coef(plt))[[1]])
nit <- length(unique(items))
coeff <- data.frame(estimate = coeff,
                    items = items,
                    node = rep(paste("Node", nodeids(plt, terminal = TRUE)),
                               times = length(items)))

# ggparty plot with node and tree info
p1 <-
  ggparty(plt) +
  geom_edge() +
  geom_edge_label() +
  geom_node_splitvar()

# node objects with coefficients
p2 <-
  ggplot(coeff, aes(x = estimate, y = items, group = node)) +
  geom_point() +
  facet_wrap(~ node)

# put together using patchwork
p <- (p1 / p2)

p

Thank you in advance

martin-borkovec commented 4 years ago

well, there might be some more sophisticated (convoluted) way to do this, but since you already have the data extracted (and I'm short on time) you can just pass it to geom_node_plot. just make sure there's a column called id containing the node id.

library("PlackettLuce")
#> Warning: package 'PlackettLuce' was built under R version 3.6.3
library("ggparty")
#> Warning: package 'ggparty' was built under R version 3.6.3
#> Loading required package: ggplot2
#> Loading required package: partykit
#> Warning: package 'partykit' was built under R version 3.6.3
#> Loading required package: grid
#> Loading required package: libcoin
#> Warning: package 'libcoin' was built under R version 3.6.3
#> Loading required package: mvtnorm

example("beans", "PlackettLuce", echo = FALSE)

nr <- nrow(beans)

# rankings into grouped rankings
G <- group(R, index = rep(1:nr, 4))

# cbind data
dat <- cbind(G, beans)

# fit PlackettLuce tree
plt <- pltree(G ~ maxTN, data = dat)

# get the coefficients
coeff <- as.vector(coef(plt, log = FALSE))
items <- rep(dimnames(coef(plt))[[2]], each = dim(coef(plt))[[1]])
nit <- length(unique(items))
coeff <- data.frame(estimate = coeff,
                    items = items,
                    id = rep(nodeids(plt, terminal = TRUE),
                               times = length(items)))

# ggparty plot with node and tree info
ggparty(plt) +
  geom_edge() +
  geom_edge_label() +
  geom_node_splitvar() +
  geom_node_plot(gglist = list(geom_point(mapping = aes(x = estimate, y = items),
                                          data = coeff)))

Created on 2020-05-26 by the reprex package (v0.3.0)

kauedesousa commented 4 years ago

Thanks @martin-borkovec that is what I was looking for. If you think that it worth it some new implementation as a function to ggparty I am willing to contribute (if needed).

Thank you