问题描述
我正在尝试编写一个函数,该函数需要一个数据帧,将列从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
。 - 用NA 替换
999
(,但仅当我指定将999
替换为NA
时) >
- 将
1
添加到col_of_interest
我的尝试
- 使用here中所述的
{{ var }}
将数据变量传递到函数参数中。 -
if
的使用基于this answer。
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))
}
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的参数。
但是,仅将na_if( {{ na_if_val }} )
合并到add_one
函数的管道中是可行的。结合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()
函数将感兴趣的变量括起来,然后在所需的位置用引号!!
对此变量取消引用。函数的另一个问题是,在管道中间插入if语句,这是行不通的。如果需要在特殊情况下应用某些方法,则需要将其与主要计算分开评估。
我通过简单地指定x
的{{1}}和y
参数来解决了这个问题。
drop_na
编辑
在@LionelHenry的评论之后,我在add_one <- function(data,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 }},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
附近删除了{{ }}
。
na_if_val