[英]Tidy Evaluation: How to use dplyr::na_if as an optional argument in a custom function that relies on a %>% pipe
我正在嘗試編寫一個函數,該函數接受一個數據幀,將一列從chr
轉換為dbl
,然后將 1 添加到一列。 我還想選擇性地用NA
替換某些值。 否則,如果不使用相關參數,我希望函數跳過 NA 替換步驟。
library(tibble)
library(dplyr)
library(magrittr)
df <-
tibble(id = 1:10, col_of_interest = 21:30) %>%
add_row(id = 11, col_of_interest = 999) %>%
mutate(across(col_of_interest, as.character))
df
## # A tibble: 11 x 2
## id col_of_interest
## <dbl> <chr>
## 1 1 21
## 2 2 22
## 3 3 23
## 4 4 24
## 5 5 25
## 6 6 26
## 7 7 27
## 8 8 28
## 9 9 29
## 10 10 30
## 11 11 999
該功能應該:
col_of_interest
從chr
轉換為dbl
。999
(但僅當我指定999
應替換為NA
)1
添加到col_of_interest
在編寫我的函數時,我受到了兩個資源的指導:
add_one <- function(data, var, na_if_val = NULL) {
data %>%
mutate(across({{ var }}, as.numeric)) %>%
{if( is.null( {{ na_if_val }} )
) . # <--- the dot means: "return the preexisting dataframe"
else
na_if( {{ na_if_val }} )
} %>%
mutate(across({{ var }}, add, 1))
}
當我在df
對象上測試函數時,出現錯誤。
add_one(data = df,
var = col_of_interest,
na_if_val = "999")
Error in check_length(y, x, fmt_args("y"), glue("same as
{fmt_args(~x)}")) : argument "y" is missing, with no default
谷歌搜索這個錯誤產生了這個頁面,說明:
但是請注意, na_if() 只能接受長度為 1 的參數。
但是,在add_one
函數的管道中僅合並na_if( {{ na_if_val }} )
確實有效。 是條件評估與is.null
結合導致函數中斷。 我不明白為什么。
你有幾個問題,但主要的一個是因為你做的非標准評估是錯誤的。
add_one <- function(data, var, na_if_val = NULL) {
var_b <- enquo(var)
data <- data %>%
mutate(across(!!var_b, as.numeric))
if(!is.null(na_if_val)){
data <- data %>%
mutate(across(!!var_b, na_if, y = na_if_val))
}
data <- data %>%
mutate(across(!!var_b, add, 1))
return(data)
}
返回這個:
add_one(df, col_of_interest, 999)
# A tibble: 11 x 2
id col_of_interest
<dbl> <dbl>
1 1 22
2 2 23
3 3 24
4 4 25
5 5 26
6 6 27
7 7 28
8 8 29
9 9 30
10 10 31
11 11 NA
首先,您需要使用enquo()
函數對感興趣的變量加enquo()
,然后在需要的位置enquo()
該變量(使用 bang bang !!
)。 您的函數的另一個問題是在管道中間插入 if 語句,這不起作用。 如果需要在特殊情況下應用某些方法,則需要與主計算分開進行評估。
我通過簡單地指定drop_na
x
和y
參數解決了這個問題。
add_one <- function(data, var, na_if_val = NULL) {
data %>%
mutate(across({{ var }}, as.numeric)) %>%
{if( is.null( {{ na_if_val }} )
) . # <--- the dot means: "return the preexisting dataframe"
else
na_if(x = ., y = {{ na_if_val }} ) ## <-- change is here
} %>%
mutate(across({{ var }}, add, 1))
}
add_one(data = df,
var = col_of_interest,
na_if_val = 999)
## # A tibble: 11 x 2
## id col_of_interest
## <dbl> <dbl>
## 1 1 22
## 2 2 23
## 3 3 24
## 4 4 25
## 5 5 26
## 6 6 27
## 7 7 28
## 8 8 29
## 9 9 30
## 10 10 31
## 11 11 NA
在@LionelHenry 的評論之后,我在na_if_val
周圍刪除了{{ }}
。
add_one <- function(data, var, na_if_val = NULL) {
data %>%
mutate(across({{ var }}, as.numeric)) %>%
{if( is.null(na_if_val)
) . # <--- the dot means: "return the preexisting dataframe"
else
na_if(x = ., y = na_if_val)
} %>%
mutate(across({{ var }}, add, 1))
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.