Search code examples
rdataframetidyversepurrrmapply

mapply that outputs a column not a list


Is there a purrr:: function to act like my mapply() call below, but output a column to be added to my data rather than a list()?

library(tidyverse)

m=
"
study group outcome
1     1       A
1     1       B
1     2       A
1     2       B
2     1       A
2     1       B
2     2       A
2     2       B
3     1       B
4     1       A
"
data =read.table(text=m,h=T)


set.seed(0)
(mapply(rnorm, n = sapply(group_split(data, study),nrow), mean=1:4*.1))

[[1]]
[1]  1.3629543 -0.2262334  1.4297993  1.3724293

[[2]]
[1]  0.61464143 -1.33995004 -0.72856703 -0.09472045

[[3]]
[1] 0.2942328

[[4]]
[1] 2.804653

Solution

  • It can be unlisted. By default mapply does SIMPLIFY = TRUE, but that is applicable only when the output list elements have the same length. Here, it is not and that is the reason it gives an output as list

    unlist((mapply(rnorm, n = sapply(group_split(data, study),nrow), mean=1:4*.1)))
    

    -output

    [1]  0.3661374 -0.2767027  2.5413646 -0.6953391  0.1451225  0.4501413  0.8182433  0.0273765 -1.9239003 -0.8636144
    

    In dplyr, we may do

    library(dplyr)
    data %>% 
       group_by(study) %>% 
       mutate(new = rnorm(n(), mean = 1:4 * .1)) %>% 
       ungroup
    # A tibble: 10 × 4
       study group outcome     new
       <int> <int> <chr>     <dbl>
     1     1     1 A        1.36  
     2     1     1 B       -0.126 
     3     1     2 A        1.63  
     4     1     2 B        1.67  
     5     2     1 A        0.515 
     6     2     1 B       -1.34  
     7     2     2 A       -0.629 
     8     2     2 B        0.105 
     9     3     1 B        0.0942
    10     4     1 A        2.50