Аргументы функции для mutate_if в dplyr работают для fun-deprecated funs (), но не для list () - PullRequest
2 голосов
/ 12 марта 2020

Я пытаюсь обновить мой следующий код, потому что funs( MY_FUN ) мягко устарел. Я знаю, что замена для этого должна быть list( ~MY_FUN ), но, похоже, это не работает для моего кода.

Вот мои фреймы данных:

fake_data <- data.frame(var1 = rep("TEMP", times = 5),
                        var2 = rep("TEMP", times = 5),
                        var3 = c(1:5),
                        stringsAsFactors = FALSE)

lookup_sub <- data.frame(var_names = c("var1", "var2", "var3"),
                         example_value = c("a", "b", "c"),
                         stringsAsFactors = FALSE)

Следующая строка кода работает и делает именно то, что я хочу:

library(tidyverse)
library(rlang)
fake_data %>%
        mutate_if(.predicate = rlang::as_function(function(x){identical("TEMP", unique(x))}),
                  .funs = funs(as.character((lookup_sub %>% filter(var_names == quo_name(quo(.))) %>% pull(example_value))[1])))

В результате

  var1 var2 var3
1    a    b    1
2    a    b    2
3    a    b    3
4    a    b    4
5    a    b    5

НО, используя аргумент без амортизации, дает все значения NA для строк, которые имеют значение ИСТИНА в предикат

fake_data %>%
        mutate_if(.predicate = rlang::as_function(function(x){identical("TEMP", unique(x))}),
                  .funs = list(~as.character((lookup_sub %>% filter(var_names == quo_name(quo(.))) %>% pull(example_value))[1])))

, что приводит к

  var1 var2 var3
1 <NA> <NA>    1
2 <NA> <NA>    2
3 <NA> <NA>    3
4 <NA> <NA>    4
5 <NA> <NA>    5

Кто-нибудь может мне это объяснить? Я знаю, что проблема возникает из-за quo_name(quo(.)), но я не знаю, как ее исправить. Спасибо!

1 Ответ

0 голосов
/ 24 марта 2020

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

Рассмотрим эти поддельные данные

smooth_data <- data.frame(`s(gam_variable_1_output)` = c(1.004, 1.345, 1.460, 1.540),
                          `s(gam_variable_2_output)` = c(1, 1, 1, 1),
                          grouping_variable_1 = c(1,2,3,4),
                          grouping_variable_2 = c("a", "b", "a", "b"),
                          grouping_variable_3 = c(500, 500, 500, 500),
                          stringsAsFactors = FALSE) 

Я хочу применить функцию ко всем гладким переменным (переменным, которые начинаются с "s ("), только если уровни этой гладкой переменной не 1 уникальное значение.

Это должно быть выполнено с помощью следующего

smooth_data %>%
mutate_if(.predicate = funs(length(unique(.)) != 1 & grepl("s\\(", quo_name(quo(.)))),
          ~2) # we'll use this for example

Так, чтобы это привело к следующему (я удалил имена / числа строк из вывода R)

s(gam_variable_1_output)
                       2
                       2
                       2
                       2
s(gam_variable_2_output)
                       1
                       1
                       1
                       1
grouping_variable_1       grouping_variable_2       grouping_variable_3
                  1                       "a"                       500
                  2                       "b"                       500
                  3                       "a"                       500
                  4                       "b"                       500

Но функция не работает. Если мы хотим разделить предикат, то мы увидим что-то интересное.

#### FIRST PART OF CONDITIONAL: only look at variables that arent a single value
## THIS WORKS
smooth_data %>% mutate_if(funs(length(unique(.)) != 1), ~2)
## ^ THAT IS THE SAME AS THIS; THIS WORKS
smooth_data %>% mutate_if(~length(unique(.)) != 1, ~2)
## THIS DOES NOT WORK
smooth_data %>% mutate_if(length(unique(.)) != 1, ~2)


#### SECOND PART OF CONDITIONAL: only look at variables that have name including `s(`
## THIS WORKS
smooth_data %>% mutate_if(grepl("s\\(", names(.)), ~2)

## THIS THROWS ERROR (BECAUSE OF `names(.)`)
smooth_data %>% mutate_if(~grepl("s\\(", names(.)), ~2)

## THIS DOES NOT WORK
smooth_data %>% mutate_if(~grepl("s\\(", quo_name(quo(.))), ~2)

## WHICH IS THE SAME AS THIS
smooth_data %>% mutate_if(funs(grepl("s\\(", quo_name(quo(.)))), ~2)

## AND THIS THROWS ERROR (BECAUSE IT NEEDS ~)
smooth_data %>% mutate_if(grepl("s\\(", quo_name(quo(.))), ~2)

Это интересно, потому что оно подсказывает мне, что моя основная строка кода не может выполняться поскольку первая часть условия должна быть в настройке funs (), а вторая часть не может быть в настройке funs (). Это не ответ на вопрос, но я думаю, что она ясно показывает проблему с mutate_if

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...