Search code examples
rdplyrdata.tablemagrittr

Separating positive and negative values in R data.table (many columns)


I was wondering how I could split many columns by their sign in a data.table. To be concrete, suppose that we have:

library(data.table)
DT = data.table(x = c(-1,-2,1,3),
                z = c(-1,-1,-1,-1))

I am looking to create a new data.table called DT_new such that it looks like:


 DT_new
    x  z x_pos x_neg z_pos z_neg
1: -1 -1     0     1     0     1
2: -2 -1     0     2     0     1
3:  1 -1     1     0     0     1
4:  3 -1     3     0     0     1

The reason I am doing this is that I want to separate out the positive and negative variables in a regression. Doing a few of these manually is easy enough. But I have hundreds of variables that I want to apply this technique to. So I am hoping that there is a "SDcols" solutions.

Thanks!


Solution

  • No need to use .SDcols ;-) Please find below a reprex:

    • Code
    DT[,`:=` (x_pos = fifelse(x>0, x, 0),
              x_neg = fifelse(x<0, abs(x), 0),
              z_pos = fifelse(z>0, z, 0),
              z_neg = fifelse(z<0, abs(z), 0))][]
    
    • Output
        x  z x_pos x_neg z_pos z_neg
    1: -1 -1     0     1     0     1
    2: -2 -1     0     2     0     1
    3:  1 -1     1     0     0     1
    4:  3 -1     3     0     0     1
    

    AS A FOLLOW-UP TO YOUR COMMENT

    Please find the reprex below.

    • Code
    vars <- c("x","z")
    suffix <- c("_pos", "_neg")
    
    DT[, CJ(vars, suffix, sorted = FALSE)[, paste0(vars, suffix)] := .(fifelse(x>0, x, 0),
                                                                       fifelse(x<0, abs(x), 0), 
                                                                       fifelse(z>0, z, 0),
                                                                       fifelse(z<0, abs(z), 0))][]
    
    • Output
    #>     x  z x_pos x_neg z_pos z_neg
    #> 1: -1 -1     0     1     0     1
    #> 2: -2 -1     0     2     0     1
    #> 3:  1 -1     1     0     0     1
    #> 4:  3 -1     3     0     0     1
    

    Created on 2021-11-28 by the reprex package (v2.0.1)