简体   繁体   中英

Mutate and replace few columns at once

I have df such as:

  outc  task  prevt 
  <fct> <fct> <fct> 
1 los   fre   rep   
2 los   fre   swi   
3 los   ins   rep   
4 los   ins   swi   
5 win   fre   rep   
6 win   fre   swi   
7 win   ins   rep   
8 win   ins   swi   

I want to replace values in column task and prevt, depending on the value in each of these columns. For example, if task is 'fre' AND prevt is 'rep', then task should be changed to 'ins' and prev should be changed to 'swi'. The key thing is that I need to change it all at once, as if I do it one after another, then the result would be different from what I want. So it seemed like easy task to do with mutate and replace:

df %>% 
  mutate(task = replace(task, task == 'fre' & prevt == 'rep', 'ins'),
         prevt = replace(prevt, task == 'fre' & prevt == 'rep', 'swi')) 

But for some reason, only the first part of mutate works in this case, ie task column is changed, but prevt column is not.

  outc  task  prevt
  <fct> <fct> <fct>
1 los   ins   rep  
2 los   fre   swi  
3 los   ins   rep  
4 los   ins   swi  
5 win   ins   rep  
6 win   fre   swi  
7 win   ins   rep  
8 win   ins   swi  

If I change second part to some non-conditional value (eg prevt = '1'), then it works.

df %>% 
  mutate(task = replace(task, which(task == 'fre' & prevt == 'rep'), 'ins'),
         prevt = '1')

  outc  task  prevt
  <fct> <fct> <chr>
1 los   ins   1    
2 los   fre   1    
3 los   ins   1    
4 los   ins   1    
5 win   ins   1    
6 win   fre   1    
7 win   ins   1    
8 win   ins   1   

So for some reason two replace does not work within mutate. Can you please help me what could I do in this case?

A base R option would be to create an object with the logical condition first (so that it won't change later) and then use Map to replace the columns with the corresponding values

i1 <- with(df, task == "fre" & prevt == "rep")
df[-1] <- Map(function(x, i) replace(x, i1, i),  df[-1], c("ins", "swi"))

Or following the same logic in OP's code, create the logical condition first and then use that

library(dplyr)
df %>% 
     mutate(i1 = task == "fre" & prevt == "rep", # create logical column 
            task = replace(task, i1, "ins"), 
            prevt = replace(prevt, i1, "swi")) %>% 
     select(-i1) # remove the logical column

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM