Hi,
Welcome to the RStudio community!
Thanks for creating a nice reproducible example, that's making this much easier. If I understand you correctly, you can do what you want to achieve in just a few lines:
library(dplyr)
library(tidyr)
value <- c(3,4,5,4,3,4,5,4,3,4,3,4,6,5,4,5,6,7,5,4,6,4,6,3,2,
6,7,4,7,8,5,6,7,5,5,7,8,7,45,3,4,3,4,6,4,3,2,1,2,3,4)
Sub <- c(rep("sub1", 10), rep("sub2",25), rep("sub3", 16))
dat <- data.frame(sub = Sub, value = value)
#Set number of groups
nGroups = 10
#Add groups column
dat = dat %>% group_by(sub) %>%
mutate(group = 0:(n()-1) %% nGroups + 1)
dat
#> # A tibble: 51 x 3
#> # Groups: sub [3]
#> sub value group
#> <chr> <dbl> <dbl>
#> 1 sub1 3 1
#> 2 sub1 4 2
#> 3 sub1 5 3
#> 4 sub1 4 4
#> 5 sub1 3 5
#> 6 sub1 4 6
#> 7 sub1 5 7
#> 8 sub1 4 8
#> 9 sub1 3 9
#> 10 sub1 4 10
#> # ... with 41 more rows
#Summarise the groups per subject
dat = dat %>%
group_by(sub, group) %>%
#Replace 'mean' by any summary function you like
summarise(value = mean(value), .groups = "drop")
dat
#> # A tibble: 30 x 3
#> sub group value
#> <chr> <dbl> <dbl>
#> 1 sub1 1 3
#> 2 sub1 2 4
#> 3 sub1 3 5
#> 4 sub1 4 4
#> 5 sub1 5 3
#> 6 sub1 6 4
#> 7 sub1 7 5
#> 8 sub1 8 4
#> 9 sub1 9 3
#> 10 sub1 10 4
#> # ... with 20 more rows
#Convert to wide format
dat = dat %>%
pivot_wider(sub, names_from = group, values_from = value)
dat
#> # A tibble: 3 x 11
#> sub `1` `2` `3` `4` `5` `6` `7` `8` `9` `10`
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 sub1 3 4 5 4 3 4 5 4 3 4
#> 2 sub2 4.67 4.67 6.33 4.33 3.67 5.5 6.5 5.5 6 6
#> 3 sub3 5 5 4 23.5 3 4 3 4 6 4
Created on 2021-12-12 by the reprex package (v2.0.1)
Here is all the functions combined into one:
dat = dat %>% group_by(sub) %>%
mutate(group = 0:(n()-1) %% 10 + 1) %>%
group_by(sub, group) %>%
summarise(value = mean(value), .groups = "drop") %>%
pivot_wider(sub, names_from = group, values_from = value)
We are now creating 10 groups by consecutively taking samples from each subject. Should you rather create random groups (still respecting the subjects of course), you can add one more line
dat = dat %>% group_by(sub) %>%
mutate(
group = 0:(n()-1) %% 10 + 1,
#Shuffle the groups within subject to make them random
group = sample(group, n())) %>%
group_by(sub, group) %>%
summarise(value = mean(value), .groups = "drop") %>%
pivot_wider(sub, names_from = group, values_from = value)
The results will now differ depending on the randomness of the groups
Hope this helps,
PJ