示例代碼:
library(tidyverse)
iris <- iris
test_tidyeval <- function(data, col_name, col_name_2, column1) {
mutate(
data,
{{col_name}} := case_when(Species == "setosa" ~ column1 Sepal.Width Petal.Length,
TRUE ~ column1),
{{col_name_2}} := case_when(Species == "setosa" ~ {{col_name}} 100,
TRUE ~ {{col_name}} 500))
}
iris %>% test_tidyeval("new_column_test", "new_column_test_2", Sepal.Length)
我確信這是一個我永遠無法理解的 tidyeval/nse 問題。
我基本上想要的是new_column_test在哪里創建如果行 Species == "setosa" 那么這是 Sepal.Length 的總和,我們column1在用戶定義的函式 Sepal.Width 和 Petal 中傳遞給它。長度,否則只回傳 Sepal.Length 的值,然后使用之前使用的相同邏輯條件new_column_test_2將 100 添加到非 setosa 物種中添加 500。new_column_test
我似乎可以操縱 case_when 的 LHS,但我堅持 RHS 陳述句。
uj5u.com熱心網友回復:
混合字串和符號時需要小心。他們的行為不同。您{{ }}在處理符號和.data[[]]處理字串時使用。這應該作業
test_tidyeval <- function(data, col_name, col_name_2, column1) {
mutate(
data,
"{col_name}" := case_when(Species == "setosa" ~ {{column1}} Sepal.Width Petal.Length,
TRUE ~ {{column1}}),
"{col_name_2}":= case_when(Species == "setosa" ~ .data[[col_name]] 100,
TRUE ~ .data[[col_name]] 500))
}
iris %>% test_tidyeval("new_column_test", "new_column_test_2", Sepal.Length) %>% str()
#'data.frame': 150 obs. of 7 variables:
# $ Sepal.Length : num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
# $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
# $ Petal.Length : num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
# $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
# $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# $ new_column_test : num 10 9.3 9.2 9.2 10 11 9.4 9.9 8.7 9.5 ...
# $ new_column_test_2: num 110 109 109 109 110 ...
如果您將所有內容都作為符號傳遞,它將如下所示
test_tidyeval <- function(data, col_name, col_name_2, column1) {
mutate(
data,
"{{col_name}}" := case_when(Species == "setosa" ~ {{column1}} Sepal.Width Petal.Length,
TRUE ~ {{column1}}),
"{{col_name_2}}":= case_when(Species == "setosa" ~ {{col_name}} 100,
TRUE ~ {{col_name}} 500))
}
iris %>% test_tidyeval(new_column_test, new_column_test_2, Sepal.Length)
uj5u.com熱心網友回復:
一些調整,這應該讓你得到你正在尋找的東西:
library(tidyverse)
library(rlang)
test_tidyeval <- function(data, col_name, col_name_2, column1) {
mutate(
data,
{{col_name}} := case_when(Species == "setosa" ~ !!enquo(column1) Sepal.Width Petal.Length,
TRUE ~ !!enquo(column1)),
{{col_name_2}} := case_when(Species == "setosa" ~ !!parse_expr(col_name) 100,
TRUE ~ !!parse_expr(col_name) 500)
)
}
iris %>%
test_tidyeval("new_column_test", "new_column_test_2", Sepal.Length) %>%
head()
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species new_column_test
#> 1 5.1 3.5 1.4 0.2 setosa 10.0
#> 2 4.9 3.0 1.4 0.2 setosa 9.3
#> 3 4.7 3.2 1.3 0.2 setosa 9.2
#> 4 4.6 3.1 1.5 0.2 setosa 9.2
#> 5 5.0 3.6 1.4 0.2 setosa 10.0
#> 6 5.4 3.9 1.7 0.4 setosa 11.0
#> new_column_test_2
#> 1 110.0
#> 2 109.3
#> 3 109.2
#> 4 109.2
#> 5 110.0
#> 6 111.0
作為簡要說明(此處使用的工具):
!!enquo(column1)首先捕獲非字符column1引數(不對其進行評估),然后!!在 RHS 中對其進行評估case_when!!parse_expr(col_name)獲取col_name字串并決議它,然后再次使用!!
uj5u.com熱心網友回復:
問題是:
column1未評估傳遞,因此我們需要{{column1}}在函式中使用col_name作為字串傳遞,因此!!sym(col_name)在函式中使用或c_across(col_name)在另一個答案中已經提到.data[[col_name]]- 請注意,由于每個
case_when's 只有 2 個臂,我們可以使用if_else陳述句更緊湊地撰寫它 - 請注意,只需要一個 dplyr 庫呼叫
盡可能接近給出的問題中的代碼
library(dplyr)
test_tidyeval <- function(data, col_name, col_name_2, column1) {
mutate(
data,
{{col_name}} := case_when(Species == "setosa" ~ {{column1}}
Sepal.Width Petal.Length,
TRUE ~ {{column1}}),
{{col_name_2}} := case_when(Species == "setosa" ~ !!sym(col_name) 100,
TRUE ~ !!sym(col_name) 500))
}
iris %>% test_tidyeval("new_column_test", "new_column_test_2", Sepal.Length)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/529085.html
