black_sheep07
black_sheep07

Reputation: 2368

Subset r data.table conditionally using is.null()

I have a data.table

library(data.table)

testDT <- data.table(
        L = (1:32), 
        M = rep(letters[23:26], each = 64), 
        N = rep(LETTERS[1:2], times = 2, each = 512),
        O = rnorm(2048, 1))

testDT$L                <- factor(testDT$L,         levels = seq(from = 1, to = 32, by = 1))

I created a function to subset the data set conditionally. If the subsetting variable G is NULL and H is "w", then I want all values within testDT$N and all values "w" in testDT$M to be returned in testDT. This is what I created, which does not function correctly:

G <- NULL 
H <- "w"

testDT1 <- testDT[if(is.null(G)) {eval(call("%in%", as.name("N"), G))} & 
                if(is.null(H)) {eval(call("%in%", as.name("M"), H))}]

I verified that everything but the if(is.null()) portion works by creating this, which subsets correctly:

G <- "A" 
H <- "w"
testDT1 <- testDT[{eval(call("%in%", as.name("N"), G))} & 
                {eval(call("%in%", as.name("M"), H))}]

How can I use the is.null() condition correctly?

Upvotes: 3

Views: 686

Answers (1)

jangorecki
jangorecki

Reputation: 16697

Using computing on the language you can prepare call object using dedicated function.

library(data.table)
testDT = data.table(
    L = factor(1:32), 
    M = rep(letters[23:26], each = 64), 
    N = rep(LETTERS[1:2], times = 2, each = 512),
    O = rnorm(2048, 1)
)

i.expr = function(var, x){
    if(is.null(x)) TRUE
    else call("%in%", as.name(var), x)
}

G = NULL
H = "w"
i.expr("N",G)
#[1] TRUE
i.expr("M",H)
#M %in% "w"
testDT1 = testDT[eval(i.expr("N",G)) & eval(i.expr("M",H))]

G = "A" 
H = "w"
i.expr("N",G)
#N %in% "A"
i.expr("M",H)
#M %in% "w"
testDT2 = testDT[eval(i.expr("N",G)) & eval(i.expr("M",H))]

If you always subset by two conditions and & operator. I would merge it into a single function so you can call it once using testDT[eval(i.expr(...))].

Upvotes: 3

Related Questions