Search code examples
rdataframedplyrrowsr-factor

rename all rows in a column based upon row with a different name


I have a dataframe like this:

 df <- setNames(data.frame(matrix(c(rep(1,8),c(1,2,3,1,2,3,4,1),
                               rep("useless",3),"label1",
                               rep("useless",3),"label2",
                               floor(runif(8,100,400))),8,4)),
                               c("subject","trial","block","data"))

     subject trial   block data
   1       1     1 useless  144
   2       1     2 useless  380
   3       1     3 useless  118
   4       1     1  label1  323
   5       1     2 useless  250
   6       1     3 useless  292
   7       1     4 useless  375
   8       1     1  label2  358

I would like to make all of the "useless" rows into the "label" rows that come after them.

Output:

   subject trial   block data
 1       1     1  label1  144
 2       1     2  label1  380
 3       1     3  label1  118
 4       1     1  label1  323
 5       1     2  label2  250
 6       1     3  label2  292
 7       1     4  label2  375
 8       1     1  label2  358

I was thinking along these lines, but don't know how to do it:

 df %>%
   mutate(block = ifelse(block == "useless", "make it the end label", block))

I know there must be a very simple solution, but I'm not seeing it. I would prefer an answer from the tidyverse, but will accept anything that works.


Solution

  • Replace useless value with NA, then do a backward fill:

    library(tidyverse)
    df %>% 
        mutate(block = ifelse(grepl('label', block), as.character(block), NA)) %>% 
        fill(block, .direction = 'up')
    
    #  subject trial  block data
    #1       1     1 label1  108
    #2       1     2 label1  391
    #3       1     3 label1  201
    #4       1     1 label1  239
    #5       1     2 label2  332
    #6       1     3 label2  239
    #7       1     4 label2  363
    #8       1     1 label2  267
    

    Or use na_if, if you have only one useless value:

    library(tidyverse)
    df %>% 
        mutate(block = na_if(block, 'useless')) %>% 
        fill(block, .direction = 'up')
    
    #  subject trial  block data
    #1       1     1 label1  108
    #2       1     2 label1  391
    #3       1     3 label1  201
    #4       1     1 label1  239
    #5       1     2 label2  332
    #6       1     3 label2  239
    #7       1     4 label2  363
    #8       1     1 label2  267