rnorouzian
rnorouzian

Reputation: 7517

Conditionally change values of data.frame but keep everything else unchanged in R

Below, I'm wondering how to only change values of my data according to the following condition:

if ir== 2, "ESL", if ir == 3, "EFL", if ir == 1, "timed", if ir == 0, "untimed"

But I wonder how to keep everything else unchanged (i.e., keep the first 3 columns unchanged)?

(ir <- data.frame(item=1:10,study.name = paste("Study", c(1,1,2,3,3,3,4,4,5,5)),
                 group.name = c(1,2,1,1,2,3,1,2,1,2),  
                 Time = c(1, 0, 1, 0, 1, 0, 1, 0, 0, 1), 
                   Time.1 = c(1, 0, 1, 0, 1, 0, 1, 1, 1, 0),
                   Setting = c(2, 2, rep(3, 8)),
                   Setting.1 = c(2, 2, 3, 2, 2, 2, 3, 3, 3, 3)))

# I have tried the following without success:

(ir1 <- data.frame(ifelse(ir== 2, "ESL", ifelse(ir == 3, "EFL", ifelse(ir == 1, "timed", "untimed")))))
 

Upvotes: 0

Views: 302

Answers (3)

Ronak Shah
Ronak Shah

Reputation: 388907

You can use recode to change the values.

library(dplyr)

ir %>%
  mutate(across(-(1:3), ~recode(., "0"="untimed",
                               "1"="timed",
                               "2"="ESL",
                               "3"="EFL")))

#   item study.name group.name    Time  Time.1 Setting Setting.1
#1     1    Study 1          1   timed   timed     ESL       ESL
#2     2    Study 1          2 untimed untimed     ESL       ESL
#3     3    Study 2          1   timed   timed     EFL       EFL
#4     4    Study 3          1 untimed untimed     EFL       ESL
#5     5    Study 3          2   timed   timed     EFL       ESL
#6     6    Study 3          3 untimed untimed     EFL       ESL
#7     7    Study 4          1   timed   timed     EFL       EFL
#8     8    Study 4          2 untimed   timed     EFL       EFL
#9     9    Study 5          1 untimed   timed     EFL       EFL
#10   10    Study 5          2   timed untimed     EFL       EFL

Upvotes: 2

Alexlok
Alexlok

Reputation: 3134

Here is a solution with across() and switch(). across() lets you specify a range of columns to which to apply a function. switch() takes an input and converts it depending on its value. You could also use dplyr::case_when(). Since switch() is not vectorized, I use map() to apply it to a whole column at once.

ir %>%
  mutate(across(Time:Setting.1,
                ~ map_chr(as.character(.x),
                          function(x) switch(x,
                                             "0"="untimed",
                                             "1"="timed",
                                             "2"="ESL",
                                             "3"="EFL"))))

Upvotes: 0

Duck
Duck

Reputation: 39595

Try this using a key dataframe and reshaping to long and wide using tidyverse functions:

library(dplyr)
library(tidyr)
#Keys
Keys <- data.frame(value=c(2,3,1,0),
                   char=c("ESL","EFL","timed","untimed"),
                   stringsAsFactors = F)
#Code
new <- ir %>%
  pivot_longer(-c(item,study.name,group.name)) %>%
  left_join(Keys) %>%
  select(-value) %>%
  pivot_wider(names_from = name,values_from=char)

Output:

# A tibble: 10 x 7
    item study.name group.name Time    Time.1  Setting Setting.1
   <int> <chr>           <dbl> <chr>   <chr>   <chr>   <chr>    
 1     1 Study 1             1 timed   timed   ESL     ESL      
 2     2 Study 1             2 untimed untimed ESL     ESL      
 3     3 Study 2             1 timed   timed   EFL     EFL      
 4     4 Study 3             1 untimed untimed EFL     ESL      
 5     5 Study 3             2 timed   timed   EFL     ESL      
 6     6 Study 3             3 untimed untimed EFL     ESL      
 7     7 Study 4             1 timed   timed   EFL     EFL      
 8     8 Study 4             2 untimed timed   EFL     EFL      
 9     9 Study 5             1 untimed timed   EFL     EFL      
10    10 Study 5             2 timed   untimed EFL     EFL      

Upvotes: 1

Related Questions