Как сделать так, чтобы row_number () и quosures работали вместе в функции R? - PullRequest
4 голосов
/ 22 февраля 2020

У меня есть результаты, полученные в дизайне участников с информацией о временных сериях для каждого испытания. Я хочу изменить условия для некоторого тестирования перестановки. Мне нужно написать функцию, и именно здесь я сталкиваюсь с проблемами.

Мои данные выглядят примерно так:

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)

(если у вас есть какие-либо указания, как я мог бы go показать этот пример лучше, я тоже был бы очень признателен)

Таким образом, чтобы добавить некоторый контекст, это результаты изучения в рамках предметов. s0 обозначает участника, c0 - условие, r0 - номер испытания (прогон). t0 - это момент времени, а v0 - интересующее значение в этот момент времени.

Я пытаюсь переставить условия внутри участников

resampledSampel <- 
  sampel %>% 
  group_by(s0, r0, c0) %>% 
  nest() %>% 
  group_by(s0) %>% 
  mutate(c1 = c0[sample(row_number())])


resampledSampel %>% 
  head(n = 12)

Это работает, как и ожидалось, но когда я пытаюсь создать функцию:

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) 

выдает ошибку :

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. 

Есть идеи, как я могу использовать mutate(condition = !!condition[sample(row_number())]) в функции? Или как я мог бы сделать все это без dplyr (это заставляет меня понять, что я, вероятно, слишком полагаюсь на dplyr ...)

Заранее спасибо. И, заранее, я прошу прощения, если способ, которым я представил вопрос, не идеален (я с удовольствием возьму несколько указаний о том, как лучше сформулировать вопросы об обмене стека. Например, я не могу понять, как отобразить структура данных)

Ответы [ 2 ]

4 голосов
/ 22 февраля 2020

Очень хороший первый вопрос!

На самом деле это просто вопрос приоритета операторов. Когда вы звоните !!condition[sample(row_number())], это интерпретируется как !!(condition[sample(row_number())]), т.е. вы пытаетесь установить подмножество quosure , а затем применить двойной взрыв, но вы означаете (!!condition)[sample(row_number())], то есть вы хочу подмножество результата двойного взрыва. Так что просто примените скобки, чтобы установить порядок оценки, и все будет работать как положено:

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) 
#> # 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
2 голосов
/ 22 февраля 2020

Мы можем использовать оператор curly-curly ({{}})

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) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...