Передача имени столбца в качестве параметра функции с помощью dplyr
У меня есть датафрейм, как показано ниже:
transid<-c(1,2,3,4,5,6,7,8)
accountid<-c(a,a,b,a,b,b,a,b)
month<-c(1,1,1,2,2,3,3,3)
amount<-c(10,20,30,40,50,60,70,80)
transactions<-data.frame(transid,accountid,month,amount)
Я пытаюсь написать функцию для общей ежемесячной суммы для каждого счета, используя глаголы пакета dplyr.
my_sum<-function(df,col1,col2,col3){
df %>% group_by_(col1,col2) %>%summarise_(total_sum = sum(col3))
}
my_sum(transactions, "accountid","month","amount")
Чтобы получить результат, как показано ниже:
accountid month total_sum
a 1 30
a 2 40
a 3 70
b 1 30
b 2 50
b 3 140
Я получаю сообщение об ошибке типа:- Ошибка в сумме (col3): неверный тип (символ) аргумента. Как передать имя столбца в качестве параметра без кавычек в функции суммирования?
2 ответа
Я бы предложил следующее решение:
my_sum <- function(df, col_to_sum,...) {
col_to_sum <- enquo(col_to_sum)
group_by <- quos(...)
df %>%
group_by(!!!group_by) %>%
summarise(total_sum = sum(!!col_to_sum)) %>%
ungroup()
}
transactions %>% my_sum(amount, accountid, month)
Результаты
>> transactions %>% my_sum(amount, accountid, month)
# A tibble: 6 x 3
accountid month total_sum
<fctr> <dbl> <dbl>
1 a 1 30
2 a 2 40
3 a 3 70
4 b 1 30
5 b 2 50
6 b 3 140
Данные
В исходном ответе вы передали строки без кавычек, я решил, что используя Hmisc:Cs
функции, но, в принципе, вы должны окружить свои струны ""
; если, конечно, вы не вызываете некоторые объекты с именем a
, b
и так далее. Это не было ясно из исходного вопроса.
Используемые данные:
transid <- c(1, 2, 3, 4, 5, 6, 7, 8)
accountid <- Hmisc::Cs(a, a, b, a, b, b, a, b)
month <- c(1, 1, 1, 2, 2, 3, 3, 3)
amount <- c(10, 20, 30, 40, 50, 60, 70, 80)
transactions <- data.frame(transid, accountid, month, amount)
Заметки
Если вы посмотрите на раздел " Захват нескольких переменных" программирования с
dplyr
В статье вы увидите, что очень похожая проблема решается с использованиемquos()
функция. По сути, ваша задача является прекрасным примером того, какquos()
Функция должна быть использована.Многоточие
...
Затем должен прийти в конце, так как предполагается, что функция будет использоваться для группировки данных с несколькими столбцами. Естественно, при желании вы можете передать столбцы один за другимenquo()
каждый столбец и так далее, но с использованием...
является более естественным и совместимым с рекомендуемым решением, рассмотренным в статье, приведенной выше. Обратите внимание, что этот подход меняет порядок аргументов в вызове вашей функции как...
должен прийти в конце.Если вы используете
summarise()
тебе не нужноungroup()
ваши данные как в моем примере. Например код:mtcars %>% group_by(am) %>% summarise(mean_disp = mean(disp)) %>% mutate(am = am + 1)
буду работать; тогда как код:
mtcars %>% group_by(am) %>% mutate(am = am + 1)
вернет ожидаемую ошибку:
Ошибка в mutate_impl(.data, точки): столбец
am
не может быть изменено, потому что это переменная группировкиВы должны использовать
ungroup()
если вы собираетесьmutate()
ваши исходные данные или делать другие операции, которые сохраняют вашу переменную группировки нетронутой. Передача сгруппированной переменной может позже оказаться проблематичной, это скажет, что это в основном вопрос вкуса / порядка в вашемdplyr
рабочий процесс. Если вы и другие пользователи функций будете помнить, что тиббл может содержать переменную группировки, тогда проблем нет; лично я склонен забывать об этом, поэтому я предпочитаюungroup()
данные, если я не заинтересован в переносе групповой переменной.
Вы можете передавать объекты quosure в качестве аргументов, используя quo()
а затем оценивать их лениво, используя некую функцию кавычек, в этом примере я использую !!
library(tidyverse)
my_sum<-function(df,col1,col2,col3){
df %>% group_by(!!col1,!!col2) %>%summarise(total_sum = sum(!!col3))
}
my_sum(transactions, quo(accountid),quo(month),quo(amount))