Oliver
Oliver

Reputation: 443

using apply within ifelse R data.table

I have the following data.table object:

USER    active  rate   day    # of elements by hour
4q7C0o  1         1.48  1       c(0, 0, 0, 0, 0, 0, 5, 98, 167, 211, 246)
2BrKY63 1         0.5   3       c(0, 0, 0, 0, 0, 0, 0, 5, 15, 24, 89, 187) 
3drUy6I 1         2.58  5       c(0, 0, 0, 0, 0, 0, 0, 0, 1, 112, 265, 309) 
G5ALtO  1         1.1   7       c(0, 0, 0, 0, 0, 0, 0, 2, 20, 153, 170)

Where each element of the column # of elements by hour is a list with varying length. I would like to apply the function pexp() to each element of each list (ex. pexp(0, rate = 1.48) to the first element of the first list and pexp(246, rate = 1.48) to the last element of the first list) and if a value less than 'x' occurs then it is displayed in a new column. Something like :

DT[, ifelse(any(lapply( of elements by hour, pexp, rate = rate) < x), 'no.usable','usable' )  ,]

However I don't know how could this be done in a short way in data.table.

Upvotes: 3

Views: 166

Answers (2)

MichaelChirico
MichaelChirico

Reputation: 34703

pexp is the exponential density, which is monotonic & easily invertible. Your condition is satisfied for rate l if:

# elem > 1 / rate * log(rate / x)

Hence we only need to look at the largest number of each list and check the condition there.

With that in mind, we can do:

DT[ , fifelse(sapply(`# elem`, max) > 1/rate*log(rate/x), 'no.usable', 'usable')]

Upvotes: 6

akrun
akrun

Reputation: 887078

Here is one option with Map where we apply the pexp on each element of "# of elements by hour" with the corresponding 'rate' column value

DT[, c('usable', 'no.usable')[unlist(Map(function(x, y)
     any(pexp(x, rate = y) < x))   `# of elements by hour`, rate)) + 1]]

Or with fifelse

DT[, fifelse(unlist(Map(function(x, y)
     any(pexp(x, rate = y) < x))   `# of elements by hour`, rate)), 
          'no.usable', 'usable')]

Upvotes: 2

Related Questions