# Function equivalent to ifelse in brms package

I wonder if there is a function equivalent to ifelse in the following code in brms package if I have more than 2 groups (five groups).

``````set.seed(1)
d <-tibble(group = rep(c("normal","cases"), each = n)) %>%
mutate(cases = ifelse(group =="normal",0,1),
y = ifelse(group =="normal",
rnorm(n, mean = mu_n, sd =1),
rnorm(n, mean = mu_c, sd =1)))
``````

@May, could you please tell us more about what youâ€™re trying to do? It looks like you want to simulate data, which is best done with other packages focused on these tasks instead of brms. If simulating data is what you want to do, I suggest looking into `dplyr::case_when` (html). This function allows you to put together multiple `if`/`ifelse` type statements. Youâ€™ll need to also use `rowwise()` to make sure that the random number generator works properly.

``````library(tidyverse)
set.seed(1)

n <- 50       # number of reps/group
mu_n <- 1  # means for each group
mu_c <- 2
mu_i <- 3
mu_j <- 4
mu_k <- 5

d <- tibble(group = rep(c("normal", "cases", "i", "j", "k"), each = n)) %>%
rowwise() %>%  # this ensures that random number generator works on each row
mutate(cases = ifelse(group =="normal", 0, 1),
y = case_when(
# logical test to identify which rows to modify ~ value to use when TRUE
group == "normal" ~ rnorm(n = 1, mean = mu_n, sd = 1),
group == "cases" ~ rnorm(n = 1, mean = mu_c, sd = 1),
group == "i" ~ rnorm(n = 1, mean = mu_i, sd = 1),
group == "j" ~ rnorm(n = 1, mean = mu_j, sd = 1),
group == "k" ~ rnorm(n = 1, mean = mu_k, sd = 1)
)) %>%
ungroup()  # remove rowwise grouping

# plot histogram of 'y' values by 'group' & colored by value of 'cases'
ggplot(d, aes(x = y, fill = cases))+
geom_histogram()+
facet_wrap(~group)
``````

That is exactly what I want, when I tried to do it in my model

``````set.seed(1)

n <- 50       # number of reps/group
mu_n <- 0  # means for each group
mu_c1 <- 0.2
mu_c2 <- 0.3
mu_c3 <- 0.3
mu_c4 <- 0.4

d <- tibble(group = rep(c("normal", "covid1", "covid2", "covid3", "covid4"), each = n)) %>%
rowwise() %>%
mutate(cases = rep(c (0, 1,2,3,4),each=n),
y = case_when(
group == "normal" ~ rnorm(n , mean = mu_n, sd = 1),
group == "covid1" ~ rnorm(n , mean = mu_c1, sd = 1),
group == "covid2" ~ rnorm(n, mean = mu_c2, sd = 1),
group == "covid3" ~ rnorm(n, mean = mu_c3, sd = 1),
group == "covid4" ~ rnorm(n, mean = mu_c4, sd = 1)
)) %>%
ungroup()
``````

I got that error

``````Error in `\$<-.data.frame`(`*tmp*`, "call_text", value = c("... %>% ungroup()", :
replacement has 6 rows, data has 2
``````

This isnâ€™t a Stan/brms issueâ€”the data manipulation is using other packages in the tidyverse and in the future would be better asked on a different forum (e.g., StackOverflow). I know itâ€™s hard to tell sometimes: at the top of the help page (e.g. type in `?mutate` to the R console), the name of the package is in curly braces (e.g., `mutate {dplyr}`). Youâ€™ll get more/better responses on this forum for the R packages listed here: Stan - Interfaces.

But weâ€™re all just trying to learn on this forum, so letâ€™s get your problem fixed anywayâ€¦
The error is caused by `rowwise()`. This treats each row as a group and does the commands that follow for each row until the grouping is changed (e.g., removed with `ungroup()`). Youâ€™re getting errors because the `mutate` commands are trying to put more than one value per row. (Note: multiple values per row is possible with list columns, but I donâ€™t think thatâ€™s what youâ€™re trying to do).

To fix:

• move the `cases = ...` line up into `tibble`. Not the only way to do this, but seems reasonable enough for your example.
• set `n = 1` for all of the `rnorm(n = ...)`s in each line of `case_when`. Remember, youâ€™re grouping by row: youâ€™re going to call `rnorm(...)` individually for each row and only one value can fit (not 50). This isnâ€™t the fastest/most efficient way to do this task, but it will get the job done and is reasonably easy for humans to read and understand.
``````d <- tibble(group = rep(c("normal", "covid1", "covid2", "covid3", "covid4"), each = n),
cases = rep(c (0, 1, 2, 3, 4), each = n)) %>%
rowwise() %>%
mutate(y = case_when(
group == "normal" ~ rnorm(n = 1, mean = mu_n, sd = 1),
group == "covid1" ~ rnorm(n = 1, mean = mu_c1, sd = 1),
group == "covid2" ~ rnorm(n = 1, mean = mu_c2, sd = 1),
group == "covid3" ~ rnorm(n = 1, mean = mu_c3, sd = 1),
group == "covid4" ~ rnorm(n = 1, mean = mu_c4, sd = 1)
)) %>%
ungroup()
``````
1 Like

You can simplify the code by setting up a data frame of simulation parameters and then generating the simulations as a list column containing the nested values:

``````library(tidyverse)

# Number of simulations per group
n = 50

# Simulation groups and parameters
params = tibble(group=c("normal","cases","i","j","k"),
cases=ifelse(group=="normal",0,1),
mu=1:5)

set.seed(1)
d = params %>%
mutate(sims = map(mu, ~rnorm(n, .x, 1)))

d
#> # A tibble: 5 Ă— 4
#>   group  cases    mu sims
#>   <chr>  <dbl> <int> <list>
#> 1 normal     0     1 <dbl [50]>
#> 2 cases      1     2 <dbl [50]>
#> 3 i          1     3 <dbl [50]>
#> 4 j          1     4 <dbl [50]>
#> 5 k          1     5 <dbl [50]>
``````
``````# Unnest if you want a "long" data frame
d %>% unnest(sims)
#> # A tibble: 250 Ă— 4
#>    group  cases    mu  sims
#>    <chr>  <dbl> <int> <dbl>
#>  1 normal     0     1 0.374
#>  2 normal     0     1 1.18
#>  3 normal     0     1 0.164
#>  4 normal     0     1 2.60
#>  5 normal     0     1 1.33
#>  6 normal     0     1 0.180
#>  7 normal     0     1 1.49
#>  8 normal     0     1 1.74
#>  9 normal     0     1 1.58
#> 10 normal     0     1 0.695
#> # â€¦ with 240 more rows
``````

Thank you very much.