I have results from a within-participants design with timeseries info about each trial. I want to reshuffle the conditions for some permutation testing. I need to write a function though and this is where I run into problems.
My data looks something like this:
library(tidyverse)
sampel <- expand.grid(s0 = 1:5, r0 = 1:12)
sampel <- sampel %>% mutate(c0 = rep(c('A', 'B'), 30))
sampel <- sampel %>%
group_by(s0, c0, r0) %>%
nest() %>%
mutate(t0 = map(data, function(t) seq(1:8)), v0 = map(data, function(v) seq(from = 0, by = runif(1), length.out = 8))) %>%
unnest(cols = c(data, t0, v0)) %>%
ungroup() %>%
mutate(s0 = paste('s', s0, sep = ''))
head(sampel, n = 12)
(if you have any pointers how I could go about displaying this example in a better way I would much appreciate it too)
So to add some context, it's results of a within-subjects study. s0 stands for participant, c0 for condition, r0 for trial number (run). t0 is a timepoint and v0 a value of interest at this timepoint.
I am trying to reshuffle conditions within-participants
resampledSampel <-
sampel %>%
group_by(s0, r0, c0) %>%
nest() %>%
group_by(s0) %>%
mutate(c1 = c0[sample(row_number())])
resampledSampel %>%
head(n = 12)
This works as hoped, but when I try to make a function:
resample_within <- function(df, subject, trial, condition) {
subject <- enquo(subject)
trial <- enquo(trial)
condition <- enquo(condition)
resampled <-
df %>%
group_by(!!subject, !!trial, !!condition) %>%
nest() %>%
group_by(!!subject) %>%
mutate(condition = !!condition[sample(row_number())]) %>%
unnest(data)
return(resampled)
}
resample_within(sampel, s0, r0, c0)
throws an error:
Error: row_number() should only be called in a data context
Run `rlang::last_error()` to see where the error occurred.
In addition: Warning message:
Subsetting quosures with `[` is deprecated as of rlang 0.4.0
Please use `quo_get_expr()` instead.
This warning is displayed once per session.
Any idea how I can use mutate(condition = !!condition[sample(row_number())])
in the function? Or how I could do all this without dplyr (it makes me realise that I probably rely on dplyr a bit too much...)
Thank you in advance. And, also in advance, I apologise if the way I presented the question is not ideal (I will gladly take any pointers on how to better formulate questions on stack exchange too. For instance I can't seem to figure out how to display the data structure)
Very nice first question!
This is actually just a matter of operator precedence. When you call !!condition[sample(row_number())]
, it is interpreted as !!(condition[sample(row_number())])
i.e. you are trying to subset the quosure then apply double bang, but you mean (!!condition)[sample(row_number())]
, that is, you want to subset the result of the double-bang. So just apply brackets to fix the order of evaluation and it works as expected:
resample_within <- function(df, subject, trial, condition) {
subject <- enquo(subject)
trial <- enquo(trial)
condition <- enquo(condition)
resampled <-
df %>%
group_by(!!subject, !!trial, !!condition) %>%
nest() %>%
group_by(!!subject) %>%
mutate(condition = (!!condition)[sample(row_number())]) %>%
unnest(data)
return(resampled)
}
Now:
resample_within(sampel, s0, r0, c0)
#> # A tibble: 480 x 6
#> # Groups: s0 [5]
#> s0 r0 c0 t0 v0 condition
#> <chr> <int> <chr> <int> <dbl> <chr>
#> 1 s1 1 A 1 0 B
#> 2 s1 1 A 2 0.981 B
#> 3 s1 1 A 3 1.96 B
#> 4 s1 1 A 4 2.94 B
#> 5 s1 1 A 5 3.93 B
#> 6 s1 1 A 6 4.91 B
#> 7 s1 1 A 7 5.89 B
#> 8 s1 1 A 8 6.87 B
#> 9 s2 1 B 1 0 A
#> 10 s2 1 B 2 0.976 A
#> # ... with 470 more rows
We can use the curly-curly ({{}}
) operator
library(dplyr)
library(tidyr)
resample_within <- function(df, subject, trial, condition) {
df %>%
group_by({{subject}}, {{trial}}, {{condition}}) %>%
nest() %>%
group_by({{subject}}) %>%
mutate(condition = ({{condition}})[sample(row_number())]) %>%
unnest(data)
}
resample_within(sampel, s0, r0, c0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With