ASKurz / Statistical_Rethinking_with_brms_ggplot2_and_the_tidyverse

The bookdown version lives here: https://bookdown.org/content/3890
GNU General Public License v3.0
393 stars 92 forks source link

Potential simplifications of some parameter name munging #20

Closed mjskay closed 5 years ago

mjskay commented 5 years ago

Love the project and also the recent post on meta-analysis. As I was reading through that post, it occurred to me that you could potentially simplify some of the parameter name munging by using tidybayes::spread_draws, tidybayes::gather_draws, or tidybayes::add_fitted_draws. E.g., this plot from your blog post on meta-analysis:

# We’ll use this custom function to add the grand mean to the group-specific deviations
add_overall_effect <- function(i){
  posterior_samples(b14.6)[, "b_Intercept"] + i
}

# load tidybayes
library(tidybayes)
posterior_samples(b14.6) %>% 
  select(starts_with("r_outcome")) %>% 
  mutate_all(add_overall_effect) %>% 
  gather(key, mu) %>% 
  # these two lines clean up the text within `key`
  mutate(key = str_remove(key, "r_outcome\\[") %>% str_remove(., ",Intercept\\]")) %>% 
  mutate(key = str_replace_all(key, "[.]", " ")) %>% 

  # plot
  ggplot(aes(x = mu, y = reorder(key, mu))) +
  geom_halfeyeh(point_interval = median_qi, .width = .95, size = 2/3) +
  labs(x = expression(italic("Cohen's d")),
       y = NULL) +
  theme(panel.grid   = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.y  = element_text(hjust = 0))

image

You could save the work munging names and lining up the global intercept with the group-level offsets by using tidybayes::spread_draws:

library(tidybayes)
b14.6 %>%
  spread_draws(b_Intercept, r_outcome[outcome,]) %>%
  mutate(mu = b_Intercept + r_outcome) %>%
  ungroup() %>%
  mutate(outcome = str_replace_all(outcome, "[.]", " ")) %>% 

  # plot
  ggplot(aes(x = mu, y = reorder(outcome, mu))) +
  geom_halfeyeh(point_interval = median_qi, .width = .95, size = 2/3) +
  labs(x = expression(italic("Cohen's d")),
       y = NULL) +
  theme(panel.grid   = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.y  = element_text(hjust = 0))

image

Or you could treat it as a problem of generating transformed linear predictors over a prediction grid by using tidybayes::add_fitted_draws along with modelr::data_grid:

library(tidybayes)
library(modelr)
spank %>%
  data_grid(outcome, se = 0) %>%
  add_fitted_draws(b14.6, re_formula = ~ (1|outcome)) %>%

  # plot
  ggplot(aes(x = .value, y = reorder(outcome, .value))) +
  geom_halfeyeh(point_interval = median_qi, .width = .95, size = 2/3) +
  labs(x = expression(italic("Cohen's d")),
       y = NULL) +
  theme(panel.grid   = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.y  = element_text(hjust = 0))

image

Let me know what you think of approaches like that --- I wasn't sure if you had pedagogical reasons for doing it a particular way. If you're amenable to changes like that, I'm happy to file pull requests in that direction (contingent on me having time for things, of course :) ).

mjskay commented 5 years ago

(also, not sure if you're doing it just to be explicit for pedagogical reasons, but if not, the default for point_interval in geom_halfeyeh is now median_qi, so you don't have to specify it if you don't want to)

ASKurz commented 5 years ago

These are good ideas! I especially like your first version; though longer, it requires fewer packages. Adopting this is really just me sitting down and learning more about tidybayes. Up to this point, I've primarily restricted myself to a few of its summary and plotting functions. As to streamlining my geom_halfeyeh() code, I suspect the unnecessary point_interval argument is just a carryover from copy/pasting older code. I think by the time users get to the end of chapter 14, that verbose variant won't do much by way of pedagogy.

ASKurz commented 5 years ago

Chapters 12—14 now reflect some of these suggestions. Thanks again!