3

I have the following data frame:

df <- data.frame("A" = c("y", "y", "n", "n"),
             "B" = c("n", NA, "y", "y"),
             "C" = c("n", "y", "y", "n"))

I would like to apply the following code to columns A and B:

df$A <- 
  df$A %>% 
  recode(
    "n" = "No",
    "y" = "Yes"
  ) %>% 
  factor(
    levels = c("No", "Yes")
  )

I tried to solve this using the following code using a for loop:

cols <- c("A", "B")

for (i in cols) {
  df$i <- 
    df$i %>% 
    recode(
      "n" = "No",
      "y" = "Yes"
    ) %>% 
    factor(
      levels = c("No", "Yes")
    )
}

However, I get this erroe message:

Error in UseMethod("recode") : 
  no applicable method for 'recode' applied to an object of class "NULL"

Can anybody help me what I am missing here? Thanks for your help!

5 Answers 5

1

Using dplyr::across you could do:

library(dplyr)

df <- data.frame("A" = c("y", "y", "n", "n"),
                 "B" = c("n", NA, "y", "y"),
                 "C" = c("n", "y", "y", "n"))

mutate(df, across(c(A, B), ~ recode(.x, "n" = "No","y" = "Yes") %>% factor(levels = c("No", "Yes"))))
#>     A    B C
#> 1 Yes   No n
#> 2 Yes <NA> y
#> 3  No  Yes y
#> 4  No  Yes n
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you!! Can you tell me, why the .x inside the recode function is needed?
To stick more closely to your code you could also do .x %>% recode("n" = ...)`. That's just a matter of habit or taste.
What I meant is, why .x is needed even though we haven't supplied this argument? I'm still new to R so I may be missing a basic concept. Would appreciate your help.
Aw. Sorry. What we are doing under the hood is we apply a function to each column specified with across, i.e. we could have used function(x) recode(x, ...). ~ recode(.x, ..) is just short-hand notation where ~ tells R here comes a function and .x (or even shorter just .) tells R what's the function argument, i.e. .x is a special notation you meet quite often when using functions from dplyr or the tidyverse in general.
Yep. That's because you used $, i.e. using df$i R looks for a column with name i in df. Instead use df[[i]].
|
1

If you want to final output to be factors you can use fct_recode from `forcats.

library(dplyr)
library(forcats)

cols <- c("A", "B")
df <- df %>% mutate(across(all_of(cols), fct_recode, "No" = "n", "Yes" = "y"))
df

#    A    B C
#1 Yes   No n
#2 Yes <NA> y
#3  No  Yes y
#4  No  Yes n

str(df)

#'data.frame':  4 obs. of  3 variables:
# $ A: Factor w/ 2 levels "No","Yes": 2 2 1 1
# $ B: Factor w/ 2 levels "No","Yes": 1 NA 2 2
# $ C: chr  "n" "y" "y" "n"

1 Comment

Where can I add ordered = TRUE within this code?
1

You can use the function factor by specifying both its levels and labels arguments:

library(dplyr)

df <- mutate(df, across(c(A, B), factor, levels=c("n", "y"), labels=c("No", "Yes")))

#     A    B C
# 1 Yes   No n
# 2 Yes <NA> y
# 3  No  Yes y
# 4  No  Yes n

2 Comments

Is it "best practice" to do it this way?
If you have few columns, then yes. But if you have many columns, it is better to replace c(A, B) expression with something like all_of(cols) where cols is a character vector containing the column names of variables we want to apply a function on.
1

Base R solution:

# Function performing a mapping replacement:
# replaceMultipleValues => function() 
replaceMultipleValues <- function(df, mapFrom, mapTo){
  valueMap <- setNames(mapTo, mapFrom)
  res <- data.frame(
    matrix(
      valueMap[unlist(df)], 
      nrow = nrow(df),
      ncol = ncol(df),
      dimnames = dimnames(df)
    )
  )
  return(res)
}

# Application of the function: 
# data.frame => stdout(console)
replaceMultipleValues(
  df, 
  c("y", "n"), 
  c("yes", "no")
)

Comments

1

We can use str_replace_all

library(stringr)
library(dplyr)
df %>%
    mutate(across(A:B, ~ str_replace_all(., setNames( c('No', 'Yes'), c('n', 'y')))))
    A    B C
1 Yes   No n
2 Yes <NA> y
3  No  Yes y
4  No  Yes n

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.