Search code examples
rdataframedata.tableshift

data.table shift right all cell values by number of na within each row [R]


How do I shift the cells in a data table TO THE RIGHT by the number of NA in each row in R?

Example Data:

data <- data.table(c1=c("a","e","h","j"),
                   c2=c("b","f","i",NA),
                   c3=c("c","g",NA,NA),
                   c4=c("d",NA,NA,NA), stringsAsFactors = F)
  c1   c2   c3   c4
1  a    b    c    d
2  e    f    g <NA>
3  h    i <NA> <NA>
4  j <NA> <NA> <NA>

Desired Data from example:

data.desired <- data.table(
                  c1=c("a",NA,NA,NA),
                   c2=c("b","e",NA,NA),
                   c3=c("c","f","h",NA),
                   c4=c("d","g","i","j"), stringsAsFactors = F)
    c1   c2   c3 c4
1    a    b    c  d
2 <NA>    e    f  g
3 <NA> <NA>    h  i
4 <NA> <NA> <NA>  j

Solution

  • Here's one attempt using matrix indexing and a counter of NA values by row:

    #convert back to a data.frame to take advantage of matrix indexing
    setDF(data)   
    
    arr <- which(!is.na(data), arr.ind=TRUE)
    arr[,"col"] <- arr[,"col"] + rowSums(is.na(data))[arr[,"row"]]
    out <- data
    out[] <- NA
    out[arr] <- data[!is.na(data)]
    
    out
    #    c1   c2   c3 c4
    #1    a    b    c  d
    #2 <NA>    e    f  g
    #3 <NA> <NA>    h  i
    #4 <NA> <NA> <NA>  j
    
    #convert to data.table if necessary
    setDT(out)
    

    This option is pretty quick and from a brief test churns through 4 columns / 2 million rows in about 3-4 seconds.