9

I'd like to pass either a named vector or two vectors to dplyr::recode. Let's say I've got:

library(dplyr)
set.seed(1)
x <- c("customer", sample(c("a", "b", "c"), 10, replace = TRUE))
recode_tbl <- tibble(letter = letters[1:3], fruit = c("apple", "banana", "cranberry"))

What I'd like to do is use the columns of recode_tbl to recode x, without having to specify the pairs manually as:

recode(x, a = "apple", b = "banana", c = "cranberry")

Something like:

recode(x, as.name(recode_tbl$letter) = recode_tbl$fruit)

That obviously doesn't work. I'm not averse to trying NSE but if someone could get the ball rolling that would be great.

Thanks.

biomiha
  • 1,358
  • 2
  • 12
  • 25

1 Answers1

8

We can do this in base R

x1 <- unname(setNames(recode_tbl$fruit, recode_tbl$letter)[x])
x1[is.na(x1)] <- x[is.na(x1)]

Or use do.call with recode

do.call(dplyr::recode, c(list(x), setNames(recode_tbl$fruit, recode_tbl$letter)))
#[1] "customer"  "apple"     "banana"    "banana"    "cranberry" "apple"
#[8] "cranberry" "cranberry" "banana"    "banana"    "apple"   
akrun
  • 874,273
  • 37
  • 540
  • 662
  • @Sotos I guess it is. Confirmed, it is (used `dplyr_0.7.0`) – akrun Jul 18 '17 at 12:15
  • 1
    I got a bit confused on the baseR-like style of the answer – Sotos Jul 18 '17 at 12:17
  • 1
    @Sotos I think there should be a way with `purrr` using `map`. – akrun Jul 18 '17 at 12:17
  • I have been digging into `purrr` lately. Those `map*` functions are really useful. – Sotos Jul 18 '17 at 12:18
  • @akrun: I want a vectorised way rather than using `purrr::map`, even though I'm a big fan of purrr. – biomiha Jul 18 '17 at 12:19
  • @biomiha Okay, then the `do.call` option would be useufl – akrun Jul 18 '17 at 13:56
  • 1
    Very helpful, so many thanks. I needed to do this for columns in a tibble. It took a while for me to work it out, possibly because I was being a little dim, but this works :- `xt <- tibble(Customer = sample(c("a", "b", "c"), 20, replace = TRUE))` `do.call(dplyr::recode, c(list(xt$Customer), setNames(recode_tbl$fruit, recode_tbl$letter)))` – astaines Sep 30 '17 at 20:08
  • how might we do this inside dplyr mutate? – Arthur Yip Apr 11 '18 at 10:26
  • ok i figured it out - it's mutate(variable = recode(variable, !!!namedlist) – Arthur Yip Apr 14 '18 at 02:44
  • @ArthurYip Sorry, I forgot to answer your comment. Glad that you got it resolved – akrun Apr 14 '18 at 02:46
  • 2
    Even though the question is quite old already: You can get around do.call by using the !!! operator. So this is the shortest call with recode: `recode(x, !!!setNames(recode_tbl$fruit, recode_tbl$letter))` – Reinhold Kainhofer Sep 15 '19 at 22:25