Kodiologist
Kodiologist

Reputation: 3495

Mark a function as data.table-unaware

I'd like a function I wrote that expects a data frame to work with data tables just as if they were data frames; e.g., I want d[, j] to do the same thing whether the argument d is a data frame or data table.

I know that data.table:::cedta is used in [.data.table to detect whether data frame compatibility mode should be on. How do I force it on for a particular function?

Upvotes: 3

Views: 74

Answers (3)

Frank
Frank

Reputation: 66819

If the only problem is what happens inside [.data.table, you can call [.data.frame instead:

library(data.table)
DT = data.table(a = 1:2, key="a")

# data.table behavior
`[`(DT, , 1)
#    a
# 1: 1
# 2: 2

# data.frame behavior
(function(d) base::`[.data.frame`(d, , 1))(DT)
# [1] 1 2

I guess the base:: prefix probably is not needed. You could also write your function into a non-CEDTA package and load it from there.

Upvotes: 2

gaut
gaut

Reputation: 5958

Most straightforward way is to differentiate explicitly..

You can detect the class of the argument passed to your function using something like this in your clauses..

a <- c(1,2,3) %>% data.table()
"data.table" %in% class(a)
#[1] TRUE
b <- c(1,2,3) %>% data.frame()
"data.table" %in% class(b)
#[1] FALSE
#  Do stuff

To avoid writing the logic twice you could apply as.data.table to the argument and then you are able to use only one type of syntax.

Upvotes: 1

Roland
Roland

Reputation: 132706

Use setDF (and setDT):

library(data.table)

DT <- data.table(x = 1:2, y = 3:4)

foo <- function(d, j) {
  test <- is.data.table(d)
  if (test) setDF(d)
  res <- d[,j]
  if (test) setDT(d) #necessary to avoid changing DT
  res
}

foo(DT, 1)
#[1] 1 2

as.data.frame(DT)[, 1]
#[1] 1 2

DT[, 1]
#   x
#1: 1
#2: 2

Upvotes: 3

Related Questions