[英]Passing column name as parameter to a function using 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包動詞編寫每個accountid的每月總量的函數。
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):參數的'type'(字符)無效。如何在匯總函數中將列名作為參數傳遞而不引用?
我建議以下解決方案:
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
在你的原始答案中,你已經通過了unqoted字符串,我已經使用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()
列傳遞一列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,dots)中的錯誤:無法修改列
am
因為它是一個分組變量
如果要mutate()
原始數據或執行其他操作以保持分組變量不變,則應使用ungroup()
。 傳遞分組變量可能后來證明是有問題的,它會說它主要是你的dplyr
工作流程中的品味/順序問題。 如果你和其他功能用戶要記住tibble可能攜帶分組變量那么就沒有問題; 就個人而言,我傾向於忘記這一點,所以如果我對攜帶分組變量不感興趣,我傾向於ungroup()
數據。
你可以使用quo()
將quosure對象作為參數傳遞,然后使用某種非引號函數懶惰地評估它們,在這個例子中我使用!!
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))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.