Мне кажется, что, поскольку вы настаиваете на передаче строк в качестве имен переменных, было бы проще и эффективнее изменить формулу для соответствия переменным, используя as.formula
, а не изменять данные. Это также избавляет вас от необходимости отдельно называть группирующую переменную внутри функции.
Следующая функция короче и примерно в два раза быстрее в тестировании, чем исходная, но поведение остается неизменным:
MyFunctionNew <- function(data, groupvar, var)
{
lst <- as.list(match.call())
if (is.symbol(lst$groupvar) || is.symbol(lst$var))
stop("Please quote all variables")
broom::tidy(aov(as.formula(paste(var, "~", groupvar)), data = data)) %>%
mutate(term = if_else(term != "Residuals", groupvar, term))
}
Вы можете видеть, что он по-прежнему работает внутри map2
:
map2(.x = outcome_vars,
.y = grouping_vars,
.f = ~ MyFunctionNew(dat = dat1,
var = tidyselect::all_of(.x),
groupvar = tidyselect::all_of(.y)))
#> $`var1 ~ Region`
#> # A tibble: 2 x 6
#> term df sumsq meansq statistic p.value
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Region 1 0.0512 0.0512 0.0427 0.836
#> 2 Residuals 198 237. 1.20 NA NA
#>
#> $`var2 ~ State`
#> # A tibble: 2 x 6
#> term df sumsq meansq statistic p.value
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 State 3 5.05 1.68 2.07 0.106
#> 2 Residuals 196 159. 0.814 NA NA
#>
#> $`var3 ~ Loc`
#> # A tibble: 2 x 6
#> term df sumsq meansq statistic p.value
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Loc 7 5.09 0.727 0.772 0.612
#> 2 Residuals 192 181. 0.943 NA NA
Что касается проверочных переменных, чтобы убедиться, что они являются строками символов, я не думаю, что это идиоматия c использование R, и может вызвать путаницу у случайных пользователей вашей функции. Другими словами, это нарушает принцип наименьшего удивления .
Например, как наивный пользователь, я ожидал бы, что смогу указать переменную группировки программно следующим образом:
MyVar <- "State"
MyFunction(data = dat1, groupvar = MyVar, var = "var1")
Однако я получаю сообщение об ошибке, говорящее мне, что все переменные должны цитироваться.
Это также означает, что ваша функция не будет работать в базовых циклах R и *apply
функциях:
lapply(c("State", "Region", "ID"), function(x) MyFunction(dat1, x, "var1"))
#> Error in MyFunction(dat1, x, "var1") : Please quote all variables
Я думаю, что это гораздо больше сбивает с толку и ограничивает, чем просто допускать ошибку выдается при использовании имени столбца без кавычек. Поэтому я думаю, что ваша производственная функция должна быть примерно такой:
MyFunction <- function(data, groupvar, var)
{
broom::tidy(aov(as.formula(paste(var, "~", groupvar)), data = data)) %>%
mutate(term = if_else(term != "Residuals", groupvar, term))
}
Что работает следующим образом:
MyFunction(data = dat1, groupvar = "State", var = "var1")
#> # A tibble: 2 x 6
#> term df sumsq meansq statistic p.value
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 State 3 1.75 0.582 0.485 0.693
#> 2 Residuals 196 235. 1.20 NA NA
MyFunction(data = dat1, groupvar = MyVar, var = "var1")
#> # A tibble: 2 x 6
#> term df sumsq meansq statistic p.value
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 State 3 1.75 0.582 0.485 0.693
#> 2 Residuals 196 235. 1.20 NA NA
MyFunction(data = dat1, groupvar = State, var = var1)
#> Error in paste(var, "~", groupvar) : object 'State' not found
Я думаю, что большинство пользователей R поймут, почему они получают эту последнюю ошибку, так как это довольно ясно. Это также ошибка, которую обычные пользователи R видели много раз. Если вы меньше доверяете своим пользователям, возможно, вы могли бы попробовать обернуть тело функции в tryCatch
, которое преобразует ошибку «символ не найден» в ошибку «пожалуйста, используйте кавычки».
В конечном итоге это может лучше всего написать функцию так, чтобы она принимала голые символы, но у меня сложилось впечатление, что вы стремитесь этого избежать, поэтому я не буду вдаваться в подробности здесь.