Extract draws from a Bayesian model for one or more variables (possibly with named dimensions) into one of two types of long-format data frames.

gather_draws(model, ..., regex = FALSE, sep = "[, ]")

spread_draws(model, ..., regex = FALSE, sep = "[, ]")

Arguments

model

A supported Bayesian model fit. Tidybayes supports a variety of model objects; for a full list of supported models, see tidybayes-models.

...

Expressions in the form of variable_name[dimension_1, dimension_2, ...] | wide_dimension. See `Details`.

regex

If TRUE, variable names are treated as regular expressions and all column matching the regular expression and number of dimensions are included in the output. Default FALSE.

sep

Separator used to separate dimensions in variable names, as a regular expression.

Value

A data frame.

Details

Imagine a JAGS or Stan fit named fit. The model may contain a variable named b[i,v] (in the JAGS or Stan language) with dimension i in 1:100 and dimension v in 1:3. However, the default format for draws returned from JAGS or Stan in R will not reflect this indexing structure, instead they will have multiple columns with names like "b[1,1]", "b[2,1]", etc.

spread_draws and gather_draws provide a straightforward syntax to translate these columns back into properly-indexed variables in two different tidy data frame formats, optionally recovering dimension types (e.g. factor levels) as it does so.

spread_draws and gather_draws return data frames already grouped by all dimensions used on the variables you specify.

The difference between spread_draws is that names of variables in the model will be spread across the data frame as column names, whereas gather_draws will gather variables into a single column named ".variable" and place values of variables into a column named ".value". To use naming schemes from other packages (such as broom), consider passing results through functions like to_broom_names or to_ggmcmc_names.

For example, spread_draws(fit, a[i], b[i,v]) might return a grouped data frame (grouped by i and v), with:

  • column ".chain": the chain number. NA if not applicable to the model type; this is typically only applicable to MCMC algorithms.

  • column ".iteration": the iteration number. Guaranteed to be unique within-chain only. NA if not applicable to the model type; this is typically only applicable to MCMC algorithms.

  • column ".draw": a unique number for each draw from the posterior. Order is not guaranteed to be meaningful.

  • column "i": value in 1:5

  • column "v": value in 1:10

  • column "a": value of "a[i]" for draw ".draw"

  • column "b": value of "b[i,v]" for draw ".draw"

gather_draws(fit, a[i], b[i,v]) on the same fit would return a grouped data frame (grouped by i and v), with:

  • column ".chain": the chain number

  • column ".iteration": the iteration number

  • column ".draw": the draw number

  • column "i": value in 1:5

  • column "v": value in 1:10, or NA if ".variable" is "a".

  • column ".variable": value in c("a", "b").

  • column ".value": value of "a[i]" (when ".variable" is "a") or "b[i,v]" (when ".variable" is "b") for draw ".draw"

spread_draws and gather_draws can use type information applied to the fit object by recover_types to convert columns back into their original types. This is particularly helpful if some of the dimensions in your model were originally factors. For example, if the v dimension in the original data frame data was a factor with levels c("a","b","c"), then we could use recover_types before spread_draws:

fit %>%
 recover_types(data) 
 spread_draws(fit, b[i,v])

Which would return the same data frame as above, except the "v" column would be a value in c("a","b","c") instead of 1:3.

For variables that do not share the same subscripts (or share some but not all subscripts), we can supply their specifications separately. For example, if we have a variable d[i] with the same i subscript as b[i,v], and a variable x with no subscripts, we could do this:

spread_draws(fit, x, d[i], b[i,v])

Which is roughly equivalent to this:

spread_draws(fit, x) %>%
 inner_join(spread_draws(fit, d[i])) %>%
 inner_join(spread_draws(fit, b[i,v])) %>%
 group_by(i,v)

Similarly, this:

gather_draws(fit, x, d[i], b[i,v])

Is roughly equivalent to this:

bind_rows(
 gather_draws(fit, x),
 gather_draws(fit, d[i]),
 gather_draws(fit, b[i,v])
)

The c and cbind functions can be used to combine multiple variable names that have the same dimensions. For example, if we have several variables with the same subscripts i and v, we could do either of these:

spread_draws(fit, c(w, x, y, z)[i,v])
spread_draws(fit, cbind(w, x, y, z)[i,v])

# equivalent

Each of which is roughly equivalent to this:

spread_draws(fit, w[i,v], x[i,v], y[i,v], z[i,v])

Besides being more compact, the c()-style syntax is currently also faster (though that may change).

Dimensions can be omitted from the resulting data frame by leaving their names blank; e.g. spread_draws(fit, b[,v]) will omit the first dimension of b from the output. This is useful if a dimension is known to contain all the same value in a given model.

The shorthand .. can be used to specify one column that should be put into a wide format and whose names will be the base variable name, plus a dot ("."), plus the value of the dimension at ... For example:

spread_draws(fit, b[i,..]) would return a grouped data frame (grouped by i), with:

  • column ".chain": the chain number

  • column ".iteration": the iteration number

  • column ".draw": the draw number

  • column "i": value in 1:20

  • column "b.1": value of "b[i,1]" for draw ".draw"

  • column "b.2": value of "b[i,2]" for draw ".draw"

  • column "b.3": value of "b[i,3]" for draw ".draw"

An optional clause in the form | wide_dimension can also be used to put the data frame into a wide format based on wide_dimension. For example, this:

spread_draws(fit, b[i,v] | v)

is roughly equivalent to this:

spread_draws(fit, b[i,v]) %>% spread(v,b)

The main difference between using the | syntax instead of the .. syntax is that the | syntax respects prototypes applied to dimensions with recover_types, and thus can be used to get columns with nicer names. For example:

fit %>% recover_types(data) %>% spread_draws(b[i,v] | v) would return a grouped data frame (grouped by i), with:

  • column ".chain": the chain number

  • column ".iteration": the iteration number

  • column ".draw": the draw number

  • column "i": value in 1:20

  • column "a": value of "b[i,1]" for draw ".draw"

  • column "b": value of "b[i,2]" for draw ".draw"

  • column "c": value of "b[i,3]" for draw ".draw"

Finally, variable names can be regular expressions by setting regex = TRUE; e.g.:

spread_draws(fit, `b_.*`[i], regex = TRUE)

Would return a tidy data frame with variables starting with `b_` and having one dimension.

See also

Examples

library(dplyr) library(ggplot2) data(RankCorr, package = "tidybayes") RankCorr %>% spread_draws(b[i, j])
#> # A tibble: 12,000 x 6 #> # Groups: i, j [12] #> .chain .iteration .draw i j b #> <int> <int> <int> <int> <int> <dbl> #> 1 1 1 1 1 1 -0.927 #> 2 1 1 1 1 2 -2.09 #> 3 1 1 1 1 3 0.111 #> 4 1 1 1 1 4 -0.000774 #> 5 1 1 1 2 1 -0.944 #> 6 1 1 1 2 2 0.652 #> 7 1 1 1 2 3 0.0440 #> 8 1 1 1 2 4 -0.171 #> 9 1 1 1 3 1 -0.164 #> 10 1 1 1 3 2 -1.14 #> # ... with 11,990 more rows
RankCorr %>% spread_draws(b[i, j], tau[i], u_tau[i])
#> # A tibble: 12,000 x 8 #> # Groups: i, j [12] #> .chain .iteration .draw i j b tau u_tau #> <int> <int> <int> <int> <int> <dbl> <dbl> <dbl> #> 1 1 1 1 1 1 -0.927 5.79 5.87 #> 2 1 1 1 1 2 -2.09 5.79 5.87 #> 3 1 1 1 1 3 0.111 5.79 5.87 #> 4 1 1 1 1 4 -0.000774 5.79 5.87 #> 5 1 1 1 2 1 -0.944 3.19 4.97 #> 6 1 1 1 2 2 0.652 3.19 4.97 #> 7 1 1 1 2 3 0.0440 3.19 4.97 #> 8 1 1 1 2 4 -0.171 3.19 4.97 #> 9 1 1 1 3 1 -0.164 3.15 5.24 #> 10 1 1 1 3 2 -1.14 3.15 5.24 #> # ... with 11,990 more rows
RankCorr %>% gather_draws(b[i, j], tau[i], u_tau[i])
#> # A tibble: 18,000 x 7 #> # Groups: i, j, .variable [18] #> .chain .iteration .draw i j .variable .value #> <int> <int> <int> <int> <int> <chr> <dbl> #> 1 1 1 1 1 1 b -0.927 #> 2 1 1 1 1 2 b -2.09 #> 3 1 1 1 1 3 b 0.111 #> 4 1 1 1 1 4 b -0.000774 #> 5 1 1 1 2 1 b -0.944 #> 6 1 1 1 2 2 b 0.652 #> 7 1 1 1 2 3 b 0.0440 #> 8 1 1 1 2 4 b -0.171 #> 9 1 1 1 3 1 b -0.164 #> 10 1 1 1 3 2 b -1.14 #> # ... with 17,990 more rows
RankCorr %>% gather_draws(tau[i], typical_r) %>% median_qi()
#> # A tibble: 4 x 8 #> # Groups: i [4] #> i .variable .value .lower .upper .width .point .interval #> <int> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> #> 1 1 tau 6.03 5.03 7.11 0.95 median qi #> 2 2 tau 3.30 2.41 4.46 0.95 median qi #> 3 3 tau 3.65 2.73 4.72 0.95 median qi #> 4 NA typical_r 0.548 0.309 0.778 0.95 median qi