stan-dev / bayesplot

bayesplot R package for plotting Bayesian models
https://mc-stan.org/bayesplot
GNU General Public License v3.0
433 stars 83 forks source link

ppc_loo_pit_overlay() doesn't draw anything and ppc_loo_pit_qq() fails #166

Closed tjmahr closed 6 years ago

tjmahr commented 6 years ago

I get two problems when running the examples ?ppc_loo_pit_overlay(). The first example doesn't draw anything. The second raises an error.

library(bayesplot)
## Not run: 
library(rstanarm)
library(loo)

head(radon)
fit <- stan_lmer(
  log_radon ~ floor + log_uranium + floor:log_uranium
  + (1 + floor | county),
  data = radon,
  iter = 1000,
  chains = 2  # ,cores = 2
)
y <- radon$log_radon
yrep <- posterior_predict(fit)

loo1 <- loo(fit, save_psis = TRUE, cores = 2)
psis1 <- loo1$psis_object
lw <- weights(psis1)

# marginal predictive check using LOO probability integral transform
color_scheme_set("orange")
ppc_loo_pit_overlay(y, yrep, lw = lw)

image

ppc_loo_pit_qq(y, yrep, lw = lw)

image

ppc_loo_pit_qq(y, yrep, lw = lw, compare = "normal")
#> Error in grid.Call.graphics(C_setviewport, vp, TRUE) : 
#>   non-finite location and/or size for viewport
#> In addition: Warning messages:
#> 1: In min(x, na.rm = na.rm) :
#>   no non-missing arguments to min; returning Inf
#> 2: In max(x, na.rm = na.rm) :
#>   no non-missing arguments to max; returning -Inf
tjmahr commented 6 years ago

For the first plot, the current code cheats by building the plot, extracting the axis scales, expanding them by a factor, and then rebuilding the plot with the expanded axis scales.

g <- ggplot_build(graph)
xylim <- g$layout$panel_ranges[[1]]
ymax <- 1.25 * xylim$y.range[2]

graph +
  scale_x_continuous(breaks = seq(from = .1, to = .9, by = .2)) +
  coord_cartesian(xlim = c(0.1, 0.9), ylim = c(0, ymax))

I say "cheat" because we pulled out the scales instead from the ggplot2 object instead of using part of the API. ggplot2 changed the internal structure of plot$layout$... so our extraction failed. Updating the code to use the official channels to expand the scale. That is,

ggplot(data) + 
  ... + 
  scale_x_continuous(
    limits = c(.1, .9),
    expand = expand_scale(0, 0),
    breaks = seq(from = .1, to = .9, by = .2)) +
  scale_y_continuous(
    limits = c(0, NA),
    expand = expand_scale(mult = c(0, .25))) +

The first plot now gives

image

tjmahr commented 6 years ago

The third plot was using the same trick to extract the axis limits and set them.

It used geom_point() and geom_abline() to draw the qqplot and then it adjusted the axis limits so that the reference qqline followed a 45-degree angle.

    # graph <- [code to draw the qq points and qq line]

    if (compare == "uniform") {
      xylim <- c(0, 1)
    } else {
      g <- ggplot_build(graph)
      xylim <- g$layout$panel_ranges[[1]]
      xylim <- range(xylim$y.range, xylim$x.range)
    }

    graph +
      coord_fixed(xlim = xylim, ylim = xylim) +
      labs(y = y_lab, x = x_lab)

But g$layout$panel_ranges doesn't work anymore, so the function breaks.

I switched to ggplot2's built-in geom_qq() and geom_qq_line(). That works.

  ggplot(data.frame(p = pit)) +
    geom_qq(
      aes_(sample = ~ p),
      distribution = theoretical,
      color = get_color("m"),
      size = size,
      alpha = alpha) +
    geom_qq_line(
      aes_(sample = ~ p),
      linetype = 2,
      distribution = theoretical,
      color = "black",
      fullrange = FALSE) +
    bayesplot_theme_get() +
    labs(x = x_lab, y = y_lab)

image

avehtari commented 6 years ago

Oh, I've seen this problem, too, but didn't have time to figure out what's going on.

Btw. we should switch to ranks. It's on my and @jgabry's todo list, but unfortunately long delayed. I'll try to make a quick proto soon

GustafRydevik commented 6 years ago

Hi, Just a note that I ran in to this bug today, and it took some digging to figure out what's going on (and find this bug report). Would it be possible to push a bug fix to cran sometime soon? I find it quite challenging getting the different builds of bayesplot, ggplot2, rstanarm, and rlang to cooperate without complaining.