Use of tidyeval based non-standard evaluation in recode in right-hand side of mutatedata.table vs dplyr: can...
Who inspired the character Geordi La Forge?
The Immortal Jellyfish
Why do military jets sometimes have elevators in a depressed position when parked?
Interrupt child processes from bash script on Ctrl+C
How to pronounce correctly [b] and [p]? As well [t]/[d] and [k]/[g]
Is there any research on the development of attacks against artificial intelligence systems?
Did I Traumatize My Puppy?
Is it allowed to let the engine of an aircraft idle without a pilot in the plane. (For both helicopters and aeroplanes)
Is there a package that allows to write correctly times in hours, minutes and seconds in mathematical mode?
Are there any Baryons that have quark-antiquark combinations?
Is it unusual that English uses possessive for past tense?
Is the phrase “You are requested” polite or rude?
Solve command does not solve this equation!
Conveying the idea of "tricky"
Are my triangles similar?
What would a chair for a Human with a Tail look like?
What is the etymology of とある?
What actually is "unallocated space"?
How to deal with people whose priority is to not get blamed?
Encountering former, abusive advisor at a conference
What plausible reasons why people forget they didn't originally live on this new planet?
A question about the Tannaka-Krein reconstruction of finite groups
Moving through the space of an invisible enemy creature in combat
Can elves trance in armor without any downsides?
Use of tidyeval based non-standard evaluation in recode in right-hand side of mutate
data.table vs dplyr: can one do something well the other can't or does poorly?Computing total rank for multiple columns using NSE syntaxHow to evaluate a constructed string with non-standard evaluation using dplyr?Conditionally mutate columns based on column classDplyr standard evaluation using a vector of multiple strings with mutate functiondplyr arrange() works with single variable inside c(), but not multiple variables inside of c() when evaluated inside of a functionComputational Efficient Hamming Distance Using `dplyr`
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{
margin-bottom:0;
}
Consider a tibble where each column is a character vector which can take many values -- let's say "A" through "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
I wish to create a function which takes a column name as an argument, and recodes that column so that any answer "A" becomes an NA and the df is otherwise returned as is. The reason for designing it this way is to fit into a broader pipeline that performs a series of operations using a given column.
There are many ways to do this. But I am interested in understanding what the best idiomatic tidy_eval/tidyverse approach would be. First, the question name needs to be on the left hand side of a mutate verb, so we use the !!
and :=
operators appropriately. But then, what to put on the right hand side?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
My initial thought was that this would work:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
But of course the bang-bang on inside the function just returns the literal character string (e.g. "q1"). I ended up taking what feels like a hacky route to reference the data on the right hand side, using the base R [[
operator and relying on the .
construct from dplyr, and it works, so in a sense I have solved my underlying problem:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
I'm interested in getting feedback from people who are very good at tidyeval as to whether there is a more idiomatic way to do this, in hopes that seeing a worked example would enhance my understanding of the tidyeval function set more generally. Any thoughts? Thanks in advance for your time.
r dplyr rlang tidyeval nse
add a comment
|
Consider a tibble where each column is a character vector which can take many values -- let's say "A" through "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
I wish to create a function which takes a column name as an argument, and recodes that column so that any answer "A" becomes an NA and the df is otherwise returned as is. The reason for designing it this way is to fit into a broader pipeline that performs a series of operations using a given column.
There are many ways to do this. But I am interested in understanding what the best idiomatic tidy_eval/tidyverse approach would be. First, the question name needs to be on the left hand side of a mutate verb, so we use the !!
and :=
operators appropriately. But then, what to put on the right hand side?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
My initial thought was that this would work:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
But of course the bang-bang on inside the function just returns the literal character string (e.g. "q1"). I ended up taking what feels like a hacky route to reference the data on the right hand side, using the base R [[
operator and relying on the .
construct from dplyr, and it works, so in a sense I have solved my underlying problem:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
I'm interested in getting feedback from people who are very good at tidyeval as to whether there is a more idiomatic way to do this, in hopes that seeing a worked example would enhance my understanding of the tidyeval function set more generally. Any thoughts? Thanks in advance for your time.
r dplyr rlang tidyeval nse
1
df %>% mutate_at(vars(q), function(y) if_else(y == "A", NA_character_, y))
– d.b
8 hours ago
Thanks, this is a clever approach -- I do use the functional approach in other parts in my code and could have thought about doing it here as well. I know some people frown on code style talk on SO, but seeing a few different styles of answer so quickly has been very fruitful for me.
– aaron
7 hours ago
1
Combining several ideas in this question, I believe this is the most succinct version that works with bothq1
(symbol) and"q1"
(string):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
– Artem Sokolov
6 hours ago
add a comment
|
Consider a tibble where each column is a character vector which can take many values -- let's say "A" through "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
I wish to create a function which takes a column name as an argument, and recodes that column so that any answer "A" becomes an NA and the df is otherwise returned as is. The reason for designing it this way is to fit into a broader pipeline that performs a series of operations using a given column.
There are many ways to do this. But I am interested in understanding what the best idiomatic tidy_eval/tidyverse approach would be. First, the question name needs to be on the left hand side of a mutate verb, so we use the !!
and :=
operators appropriately. But then, what to put on the right hand side?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
My initial thought was that this would work:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
But of course the bang-bang on inside the function just returns the literal character string (e.g. "q1"). I ended up taking what feels like a hacky route to reference the data on the right hand side, using the base R [[
operator and relying on the .
construct from dplyr, and it works, so in a sense I have solved my underlying problem:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
I'm interested in getting feedback from people who are very good at tidyeval as to whether there is a more idiomatic way to do this, in hopes that seeing a worked example would enhance my understanding of the tidyeval function set more generally. Any thoughts? Thanks in advance for your time.
r dplyr rlang tidyeval nse
Consider a tibble where each column is a character vector which can take many values -- let's say "A" through "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
I wish to create a function which takes a column name as an argument, and recodes that column so that any answer "A" becomes an NA and the df is otherwise returned as is. The reason for designing it this way is to fit into a broader pipeline that performs a series of operations using a given column.
There are many ways to do this. But I am interested in understanding what the best idiomatic tidy_eval/tidyverse approach would be. First, the question name needs to be on the left hand side of a mutate verb, so we use the !!
and :=
operators appropriately. But then, what to put on the right hand side?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
My initial thought was that this would work:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
But of course the bang-bang on inside the function just returns the literal character string (e.g. "q1"). I ended up taking what feels like a hacky route to reference the data on the right hand side, using the base R [[
operator and relying on the .
construct from dplyr, and it works, so in a sense I have solved my underlying problem:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
I'm interested in getting feedback from people who are very good at tidyeval as to whether there is a more idiomatic way to do this, in hopes that seeing a worked example would enhance my understanding of the tidyeval function set more generally. Any thoughts? Thanks in advance for your time.
r dplyr rlang tidyeval nse
r dplyr rlang tidyeval nse
asked 8 hours ago
aaronaaron
604 bronze badges
604 bronze badges
1
df %>% mutate_at(vars(q), function(y) if_else(y == "A", NA_character_, y))
– d.b
8 hours ago
Thanks, this is a clever approach -- I do use the functional approach in other parts in my code and could have thought about doing it here as well. I know some people frown on code style talk on SO, but seeing a few different styles of answer so quickly has been very fruitful for me.
– aaron
7 hours ago
1
Combining several ideas in this question, I believe this is the most succinct version that works with bothq1
(symbol) and"q1"
(string):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
– Artem Sokolov
6 hours ago
add a comment
|
1
df %>% mutate_at(vars(q), function(y) if_else(y == "A", NA_character_, y))
– d.b
8 hours ago
Thanks, this is a clever approach -- I do use the functional approach in other parts in my code and could have thought about doing it here as well. I know some people frown on code style talk on SO, but seeing a few different styles of answer so quickly has been very fruitful for me.
– aaron
7 hours ago
1
Combining several ideas in this question, I believe this is the most succinct version that works with bothq1
(symbol) and"q1"
(string):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
– Artem Sokolov
6 hours ago
1
1
df %>% mutate_at(vars(q), function(y) if_else(y == "A", NA_character_, y))
– d.b
8 hours ago
df %>% mutate_at(vars(q), function(y) if_else(y == "A", NA_character_, y))
– d.b
8 hours ago
Thanks, this is a clever approach -- I do use the functional approach in other parts in my code and could have thought about doing it here as well. I know some people frown on code style talk on SO, but seeing a few different styles of answer so quickly has been very fruitful for me.
– aaron
7 hours ago
Thanks, this is a clever approach -- I do use the functional approach in other parts in my code and could have thought about doing it here as well. I know some people frown on code style talk on SO, but seeing a few different styles of answer so quickly has been very fruitful for me.
– aaron
7 hours ago
1
1
Combining several ideas in this question, I believe this is the most succinct version that works with both
q1
(symbol) and "q1"
(string): df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
– Artem Sokolov
6 hours ago
Combining several ideas in this question, I believe this is the most succinct version that works with both
q1
(symbol) and "q1"
(string): df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
– Artem Sokolov
6 hours ago
add a comment
|
3 Answers
3
active
oldest
votes
Here, on the right side of :=
, we can specify sym
to convert to symbol and then evaluate (!!
)
fix_question <- function(df, question) {
df %>%
mutate(!!question := recode(!! rlang::sym(question), "A" = NA_character_))
}
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
A better approach that would work for both quoted and unquoted input is ensym
fix_question <- function(df, question) {
question <- ensym(question)
df %>%
mutate(!!question := recode(!! question, "A" = NA_character_))
}
fix_question(sample_df, q1)
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
2
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
add a comment
|
You can use the "curly curly" method now if you have rlang >= 0.4.0.
Explanation thanks to @eipi10:
This combines the two step process of quote-then-unquote into one step, so {{question}}
is equivalent to !!enquo(question)
fix_question <- function(df, question){
df %>% mutate({{question}} := recode({{question}}, A = NA_character_))
}
fix_question(sample_df, q1)
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 NA B
# 2 B B
# 3 C A
Note that unlike the ensym
approach, this doesn't work with character names. Even worse, it does the wrong thing instead of just giving an error.
fix_question(sample_df, 'q1')
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 q1 B
# 2 q1 B
# 3 q1 A
2
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
1
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
2
I think the bang-bang didn't work becausequestion
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe.{{question}}
is equivalent to!!enquo(question)
.
– eipi10
7 hours ago
2
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
|
show 1 more comment
You can make the function a bit more flexible by allowing a vector of recoded values to be entered as an argument as well. For example:
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
fix_question <- function(df, question, recode.vec) {
df %>% mutate({{question}} := recode({{question}}, !!!recode.vec))
}
fix_question(sample_df, q1, c(A=NA_character_, B="Was B"))
q1 q2
1 <NA> B
2 Was B B
3 C A
Note that recode.vec
is "unquote-spliced" with !!!
. I'm not exactly sure why !!!recode.vec
is the idiom needed here, since !!!
is used to unquote a list of quosures, while in this case we have a named character vector.
Or, if you want to potentially run this on multiple columns, turn it into a function that takes just a column name and a recoding vector. This approach seems like it would be more pipe-friendly.
fix_question <- function(question, recode.vec) {
recode({{question}}, !!!recode.vec)
}
sample_df %>%
mutate_at(vars(matches("q")), list(~fix_question(., c(A=NA_character_, B="Was B"))))
q1 q2
1 <NA> Was B
2 Was B Was B
3 C <NA>
Or for a single column:
sample_df %>%
mutate(q1 = fix_question(q1, c(A=NA_character_, B="Was B")))
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f58346170%2fuse-of-tidyeval-based-non-standard-evaluation-in-recode-in-right-hand-side-of-mu%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here, on the right side of :=
, we can specify sym
to convert to symbol and then evaluate (!!
)
fix_question <- function(df, question) {
df %>%
mutate(!!question := recode(!! rlang::sym(question), "A" = NA_character_))
}
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
A better approach that would work for both quoted and unquoted input is ensym
fix_question <- function(df, question) {
question <- ensym(question)
df %>%
mutate(!!question := recode(!! question, "A" = NA_character_))
}
fix_question(sample_df, q1)
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
2
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
add a comment
|
Here, on the right side of :=
, we can specify sym
to convert to symbol and then evaluate (!!
)
fix_question <- function(df, question) {
df %>%
mutate(!!question := recode(!! rlang::sym(question), "A" = NA_character_))
}
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
A better approach that would work for both quoted and unquoted input is ensym
fix_question <- function(df, question) {
question <- ensym(question)
df %>%
mutate(!!question := recode(!! question, "A" = NA_character_))
}
fix_question(sample_df, q1)
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
2
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
add a comment
|
Here, on the right side of :=
, we can specify sym
to convert to symbol and then evaluate (!!
)
fix_question <- function(df, question) {
df %>%
mutate(!!question := recode(!! rlang::sym(question), "A" = NA_character_))
}
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
A better approach that would work for both quoted and unquoted input is ensym
fix_question <- function(df, question) {
question <- ensym(question)
df %>%
mutate(!!question := recode(!! question, "A" = NA_character_))
}
fix_question(sample_df, q1)
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
Here, on the right side of :=
, we can specify sym
to convert to symbol and then evaluate (!!
)
fix_question <- function(df, question) {
df %>%
mutate(!!question := recode(!! rlang::sym(question), "A" = NA_character_))
}
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
A better approach that would work for both quoted and unquoted input is ensym
fix_question <- function(df, question) {
question <- ensym(question)
df %>%
mutate(!!question := recode(!! question, "A" = NA_character_))
}
fix_question(sample_df, q1)
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
fix_question(sample_df, "q1")
# A tibble: 3 x 2
# q1 q2
# <chr> <chr>
#1 <NA> B
#2 B B
#3 C A
answered 8 hours ago
akrunakrun
476k15 gold badges265 silver badges346 bronze badges
476k15 gold badges265 silver badges346 bronze badges
2
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
add a comment
|
2
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
2
2
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
I had tried to putz around with a few of the rlang conversion functions but obviously didn't choose the right one, but your approach works -- I think really I just need to workflow the type conversions in my head. My !!question doesn't work because it evaluates a character string literally. Yours works because it first converts the character string to a symbol, and then evaluates the symbol, returning the vector. I just couldn't wrap my head that that was the order of operations. Thanks again.
– aaron
7 hours ago
add a comment
|
You can use the "curly curly" method now if you have rlang >= 0.4.0.
Explanation thanks to @eipi10:
This combines the two step process of quote-then-unquote into one step, so {{question}}
is equivalent to !!enquo(question)
fix_question <- function(df, question){
df %>% mutate({{question}} := recode({{question}}, A = NA_character_))
}
fix_question(sample_df, q1)
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 NA B
# 2 B B
# 3 C A
Note that unlike the ensym
approach, this doesn't work with character names. Even worse, it does the wrong thing instead of just giving an error.
fix_question(sample_df, 'q1')
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 q1 B
# 2 q1 B
# 3 q1 A
2
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
1
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
2
I think the bang-bang didn't work becausequestion
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe.{{question}}
is equivalent to!!enquo(question)
.
– eipi10
7 hours ago
2
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
|
show 1 more comment
You can use the "curly curly" method now if you have rlang >= 0.4.0.
Explanation thanks to @eipi10:
This combines the two step process of quote-then-unquote into one step, so {{question}}
is equivalent to !!enquo(question)
fix_question <- function(df, question){
df %>% mutate({{question}} := recode({{question}}, A = NA_character_))
}
fix_question(sample_df, q1)
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 NA B
# 2 B B
# 3 C A
Note that unlike the ensym
approach, this doesn't work with character names. Even worse, it does the wrong thing instead of just giving an error.
fix_question(sample_df, 'q1')
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 q1 B
# 2 q1 B
# 3 q1 A
2
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
1
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
2
I think the bang-bang didn't work becausequestion
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe.{{question}}
is equivalent to!!enquo(question)
.
– eipi10
7 hours ago
2
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
|
show 1 more comment
You can use the "curly curly" method now if you have rlang >= 0.4.0.
Explanation thanks to @eipi10:
This combines the two step process of quote-then-unquote into one step, so {{question}}
is equivalent to !!enquo(question)
fix_question <- function(df, question){
df %>% mutate({{question}} := recode({{question}}, A = NA_character_))
}
fix_question(sample_df, q1)
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 NA B
# 2 B B
# 3 C A
Note that unlike the ensym
approach, this doesn't work with character names. Even worse, it does the wrong thing instead of just giving an error.
fix_question(sample_df, 'q1')
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 q1 B
# 2 q1 B
# 3 q1 A
You can use the "curly curly" method now if you have rlang >= 0.4.0.
Explanation thanks to @eipi10:
This combines the two step process of quote-then-unquote into one step, so {{question}}
is equivalent to !!enquo(question)
fix_question <- function(df, question){
df %>% mutate({{question}} := recode({{question}}, A = NA_character_))
}
fix_question(sample_df, q1)
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 NA B
# 2 B B
# 3 C A
Note that unlike the ensym
approach, this doesn't work with character names. Even worse, it does the wrong thing instead of just giving an error.
fix_question(sample_df, 'q1')
# # A tibble: 3 x 2
# q1 q2
# <chr> <chr>
# 1 q1 B
# 2 q1 B
# 3 q1 A
edited 7 hours ago
answered 8 hours ago
IceCreamToucanIceCreamToucan
16k2 gold badges9 silver badges20 bronze badges
16k2 gold badges9 silver badges20 bronze badges
2
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
1
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
2
I think the bang-bang didn't work becausequestion
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe.{{question}}
is equivalent to!!enquo(question)
.
– eipi10
7 hours ago
2
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
|
show 1 more comment
2
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
1
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
2
I think the bang-bang didn't work becausequestion
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe.{{question}}
is equivalent to!!enquo(question)
.
– eipi10
7 hours ago
2
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
2
2
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
I haven't gotten into the "curly curly" habit yet. Do you know why this works, whereas the OP's seemingly-identical "bang bang" version didn't?
– camille
8 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
Thanks for mentioning curly-curly, which I had heard was upcoming. The answer does not work for whatever version of rlang/dplyr I have installed; I get an error with the LHS. If I replace the LHS with my LHS and quote q1, I get the same problem I had above; if I don't quote q1, I get an error. This is possibly a version thing.
– aaron
7 hours ago
1
1
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
Yeah rlang 0.4.0 was just released at the end of June so if you haven't updated it since then this won't work for you
– IceCreamToucan
7 hours ago
2
2
I think the bang-bang didn't work because
question
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe. {{question}}
is equivalent to !!enquo(question)
.– eipi10
7 hours ago
I think the bang-bang didn't work because
question
first needs to be turned into a quosure (question = enquo(question)
) before being used in the dplyr pipe. {{question}}
is equivalent to !!enquo(question)
.– eipi10
7 hours ago
2
2
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
You need enquo for the first instance of question too for that to be equivalent.
– IceCreamToucan
7 hours ago
|
show 1 more comment
You can make the function a bit more flexible by allowing a vector of recoded values to be entered as an argument as well. For example:
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
fix_question <- function(df, question, recode.vec) {
df %>% mutate({{question}} := recode({{question}}, !!!recode.vec))
}
fix_question(sample_df, q1, c(A=NA_character_, B="Was B"))
q1 q2
1 <NA> B
2 Was B B
3 C A
Note that recode.vec
is "unquote-spliced" with !!!
. I'm not exactly sure why !!!recode.vec
is the idiom needed here, since !!!
is used to unquote a list of quosures, while in this case we have a named character vector.
Or, if you want to potentially run this on multiple columns, turn it into a function that takes just a column name and a recoding vector. This approach seems like it would be more pipe-friendly.
fix_question <- function(question, recode.vec) {
recode({{question}}, !!!recode.vec)
}
sample_df %>%
mutate_at(vars(matches("q")), list(~fix_question(., c(A=NA_character_, B="Was B"))))
q1 q2
1 <NA> Was B
2 Was B Was B
3 C <NA>
Or for a single column:
sample_df %>%
mutate(q1 = fix_question(q1, c(A=NA_character_, B="Was B")))
add a comment
|
You can make the function a bit more flexible by allowing a vector of recoded values to be entered as an argument as well. For example:
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
fix_question <- function(df, question, recode.vec) {
df %>% mutate({{question}} := recode({{question}}, !!!recode.vec))
}
fix_question(sample_df, q1, c(A=NA_character_, B="Was B"))
q1 q2
1 <NA> B
2 Was B B
3 C A
Note that recode.vec
is "unquote-spliced" with !!!
. I'm not exactly sure why !!!recode.vec
is the idiom needed here, since !!!
is used to unquote a list of quosures, while in this case we have a named character vector.
Or, if you want to potentially run this on multiple columns, turn it into a function that takes just a column name and a recoding vector. This approach seems like it would be more pipe-friendly.
fix_question <- function(question, recode.vec) {
recode({{question}}, !!!recode.vec)
}
sample_df %>%
mutate_at(vars(matches("q")), list(~fix_question(., c(A=NA_character_, B="Was B"))))
q1 q2
1 <NA> Was B
2 Was B Was B
3 C <NA>
Or for a single column:
sample_df %>%
mutate(q1 = fix_question(q1, c(A=NA_character_, B="Was B")))
add a comment
|
You can make the function a bit more flexible by allowing a vector of recoded values to be entered as an argument as well. For example:
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
fix_question <- function(df, question, recode.vec) {
df %>% mutate({{question}} := recode({{question}}, !!!recode.vec))
}
fix_question(sample_df, q1, c(A=NA_character_, B="Was B"))
q1 q2
1 <NA> B
2 Was B B
3 C A
Note that recode.vec
is "unquote-spliced" with !!!
. I'm not exactly sure why !!!recode.vec
is the idiom needed here, since !!!
is used to unquote a list of quosures, while in this case we have a named character vector.
Or, if you want to potentially run this on multiple columns, turn it into a function that takes just a column name and a recoding vector. This approach seems like it would be more pipe-friendly.
fix_question <- function(question, recode.vec) {
recode({{question}}, !!!recode.vec)
}
sample_df %>%
mutate_at(vars(matches("q")), list(~fix_question(., c(A=NA_character_, B="Was B"))))
q1 q2
1 <NA> Was B
2 Was B Was B
3 C <NA>
Or for a single column:
sample_df %>%
mutate(q1 = fix_question(q1, c(A=NA_character_, B="Was B")))
You can make the function a bit more flexible by allowing a vector of recoded values to be entered as an argument as well. For example:
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
fix_question <- function(df, question, recode.vec) {
df %>% mutate({{question}} := recode({{question}}, !!!recode.vec))
}
fix_question(sample_df, q1, c(A=NA_character_, B="Was B"))
q1 q2
1 <NA> B
2 Was B B
3 C A
Note that recode.vec
is "unquote-spliced" with !!!
. I'm not exactly sure why !!!recode.vec
is the idiom needed here, since !!!
is used to unquote a list of quosures, while in this case we have a named character vector.
Or, if you want to potentially run this on multiple columns, turn it into a function that takes just a column name and a recoding vector. This approach seems like it would be more pipe-friendly.
fix_question <- function(question, recode.vec) {
recode({{question}}, !!!recode.vec)
}
sample_df %>%
mutate_at(vars(matches("q")), list(~fix_question(., c(A=NA_character_, B="Was B"))))
q1 q2
1 <NA> Was B
2 Was B Was B
3 C <NA>
Or for a single column:
sample_df %>%
mutate(q1 = fix_question(q1, c(A=NA_character_, B="Was B")))
edited 3 hours ago
answered 7 hours ago
eipi10eipi10
64.9k17 gold badges122 silver badges187 bronze badges
64.9k17 gold badges122 silver badges187 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f58346170%2fuse-of-tidyeval-based-non-standard-evaluation-in-recode-in-right-hand-side-of-mu%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
df %>% mutate_at(vars(q), function(y) if_else(y == "A", NA_character_, y))
– d.b
8 hours ago
Thanks, this is a clever approach -- I do use the functional approach in other parts in my code and could have thought about doing it here as well. I know some people frown on code style talk on SO, but seeing a few different styles of answer so quickly has been very fruitful for me.
– aaron
7 hours ago
1
Combining several ideas in this question, I believe this is the most succinct version that works with both
q1
(symbol) and"q1"
(string):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
– Artem Sokolov
6 hours ago