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;
}








6

















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.










share|improve this question






















  • 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


















6

















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.










share|improve this question






















  • 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














6












6








6


3






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.










share|improve this question















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






share|improve this question














share|improve this question











share|improve this question




share|improve this question










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 both q1 (symbol) and "q1" (string): df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)

    – Artem Sokolov
    6 hours ago














  • 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








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












3 Answers
3






active

oldest

votes


















4


















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





share|improve this answer






















  • 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



















6


















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





share|improve this answer
























  • 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 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





    You need enquo for the first instance of question too for that to be equivalent.

    – IceCreamToucan
    7 hours ago



















5


















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")))





share|improve this answer






























    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
    });


    }
    });















    draft saved

    draft discarded
















    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









    4


















    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





    share|improve this answer






















    • 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
















    4


















    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





    share|improve this answer






















    • 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














    4














    4










    4









    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





    share|improve this answer














    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






    share|improve this answer













    share|improve this answer




    share|improve this answer










    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














    • 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













    6


















    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





    share|improve this answer
























    • 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 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





      You need enquo for the first instance of question too for that to be equivalent.

      – IceCreamToucan
      7 hours ago
















    6


















    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





    share|improve this answer
























    • 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 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





      You need enquo for the first instance of question too for that to be equivalent.

      – IceCreamToucan
      7 hours ago














    6














    6










    6









    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





    share|improve this answer
















    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






    share|improve this answer















    share|improve this answer




    share|improve this answer








    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 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





      You need enquo for the first instance of question too for that to be equivalent.

      – IceCreamToucan
      7 hours ago














    • 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 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





      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











    5


















    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")))





    share|improve this answer

































      5


















      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")))





      share|improve this answer































        5














        5










        5









        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")))





        share|improve this answer
















        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")))






        share|improve this answer















        share|improve this answer




        share|improve this answer








        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


































            draft saved

            draft discarded



















































            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.




            draft saved


            draft discarded














            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





















































            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









            Popular posts from this blog

            Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

            Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

            Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...