---
title: "Gamma"
format:
  html:
    toc: true
    number-depth: 3
    toc-location: left
    embed-resources: true
---

## Resources

- https://discourse.mc-stan.org/t/output-for-family-in-brms/9379
- https://discourse.mc-stan.org/t/decoding-smooth-fits-in-brms/34473
- https://stats.stackexchange.com/questions/96972/how-to-interpret-parameters-in-glm-with-family-gamma

```{r}
#| label: setup
#| message: false
#| warning: false

library(tidyverse)
library(brms)
library(posterior)
library(bayesplot)
library(ggdist)
library(patchwork)

color_scheme_set(scheme = "red")
theme_set(theme_ggdist())

prior_pred_lines <- function(post) {
  map(.x = seq_len(nrow(post)),
    .f = function(ii, post){
      p_Intercept <- post$b_Intercept[ii]
      p_shape <- post$shape[ii]
      tibble(ii = ii,
             x = seq(0, 30, length.out = 100),
             y = dgamma(x, shape = exp(p_Intercept), rate = 1 / p_shape))
    }, post = post) |> 
  list_rbind()
}

```

## Gamma distribution

Shape ($\theta$) and Scale ($k$):

$$PDF(x)=\frac{1}{\Gamma(k)~\theta^k} x^{k - 1}~e^{-x/\theta}$$


Shape ($\alpha = \theta$) and Rate ($\beta$): 

$$PDF(x) = \frac{\beta^\alpha}{\Gamma(\alpha)} x^{\alpha - 1}~e^{-\beta x}$$

where $\Gamma$ is the Gamma function

Inverse scale parameter = rate:

$$\beta = \frac{1}{\theta} = \frac{1}{\alpha}$$

Mean:

$$\bar{x} = \mu = \frac{\alpha}{\beta}$$


## Data

```{r}
set.seed(3475934)

x_mean <- 4
alpha <- 12
(beta <- alpha / x_mean)

n <- 1e4

GD <- tibble(x = rgamma(n, shape = alpha, rate = beta))
```

```{r}
#| echo: false

ggplot(GD, aes(x)) +
  stat_dotsinterval() +
ggplot(GD, aes(log(x))) +
  stat_dotsinterval()
```


```{r}
alpha / beta
mean(GD$x)
```

$$Var(x) = \frac{\alpha}{\beta^2}$$

```{r}
alpha / (beta^2)
var(GD$x)
```

$$Var(x) = \phi~\mu^2$$

where $\phi$ is a *dispersion* parameter

```{r}
(alpha / (beta^2)) / ((alpha / beta)^2)
```


## GLM 

```{r}
fm_glm <- glm(x ~ 1, data = GD, family = Gamma(link = log))
summary(fm_glm)
```

## Mean

$$\mu = \exp(\alpha + \beta~x)$$

```{r}
(fm_beta <- coef(fm_glm))
exp(fm_beta)
alpha / beta

# alpha
1 / MASS::gamma.dispersion(fm_glm)
```


## Priors

```{r}
get_prior(x ~ 1,
          family = Gamma(link = log),
          data = GD)
```


## Prior prediction - default

```{r}
#| message: false

priors <- c(prior(student_t(3, 1.4, 2.5), class = "Intercept"),
            prior(gamma(0.01, 0.01), class = "shape"))

PP <- brm(x ~ 1,
          family = Gamma(link = log),
          prior = priors,
          data = GD,
          sample_prior = "only",
          backend = "cmdstanr",
          refresh = 0)

(post <- as_draws_df(PP) |> 
  slice_sample(n = 200))

ggplot() +
  geom_line(data = prior_pred_lines(post), aes(x, y, group = ii),
            color = "firebrick4", alpha = 0.5) +
  geom_dotsinterval(data = GD, aes(x))
```


## Prior prediction - improved

```{r}
(pr_mean <- log(mean(GD$x))) |> round(2)
priors <- c(prior(student_t(3, 1.4, 2.5), class = "Intercept"),
            prior(gamma(1.4, 1/1.4), class = "shape"))

PP <- brm(x ~ 1,
          family = Gamma(link = log),
          prior = priors,
          data = GD,
          backend = "cmdstanr",
          sample_prior = "only",
          refresh = 0)

(post <- as_draws_df(PP) |> 
  slice_sample(n = 200))

ggplot() +
  geom_line(data = prior_pred_lines(post), aes(x, y, group = ii),
            color = "firebrick4", alpha = 0.5) +
  geom_dotsinterval(data = GD, aes(x))
```


## brms model

```{r}
fm <- brm(x ~ 1,
          family = Gamma(link = log),
          data = GD,
          prior = priors,
          backend = "cmdstanr",
          cores = 4,
          init = list(list(Intercept = 1, shape = 2),
                      list(Intercept = 1, shape = 2),
                      list(Intercept = 1, shape = 2),
                      list(Intercept = 1, shape = 2)),
          control = list(step_size = 0.01),
          refresh = 0)
```

```{r}
prior_summary(fm)
```

```{r}
mcmc_combo(fm, pars = c("b_Intercept", "shape"),
           combo = c("dens_overlay", "rank_overlay"))

pp_check(fm, ndraws = 100)
```


```{r}
ps <- posterior_summary(fm)
```


```{r}
(mean_est <- exp(ps[1, 1]))
mean(GD$x)
```

