2

I'm building an R package in which I would like to use dtplyr to perform various bits of data manipulation. My issue is that dtplyr seems to only work if I import the whole of data.table (i.e. using the roxygen #' @import data.table). Without this I get errors like:

Error in .(x = sum(x), y = sum(y),  : 
  could not find function "." 

If I can solve this problem by only importing certain functions from data.table that would be great, but there seems to be no function .() in the package. My knowledge of data.table is limited, but I can only assume it uses .() to edit parsed code (similar to the base R bquote()), but that dtplyr for some reason needs data.table to be loaded for this to work.

I've tried various things such as withr::with_package("data.table", code) and requireNamespace("data.table"), but so far importing the whole package is the only thing that seems to work. This is not a viable solution because it completely ruins the well-maintained namespace in the package I'm working on by importing so many functions from data.table.

NB, this package houses a project which will be worked on by many other analysts well into the future. While simply writing data.table code may be preferable in terms of performance and general good-practice, using dtplyr to translate dplyr code gives a boost in readability and ease-of-use that is far more important in this context.

wurli
  • 2,314
  • 10
  • 17
  • Can you try `importFrom data.table ` in the NAMESPACE – akrun Oct 12 '21 at 17:47
  • This results in an error when running `devtools::load_all()`: `Error in asChar(ivars) : empty name in directive 'importFrom' in 'NAMESPACE' file` :( – wurli Oct 12 '21 at 17:49
  • I think the `importFrom` at two places i.e. NAMESPACE and in the function should have worked `importFrom data.table .` – akrun Oct 12 '21 at 17:57
  • Using `#' @importFrom data.table .` then running `document()` and `load_all()` doesn't seem to fix it for me. I get the same error as well as `Warning message: object ‘.’ is not exported by 'namespace:data.table' ` when running `load_all()`. As I said, I think this is because `data.table` doesn't actually export `.()` as a function – wurli Oct 12 '21 at 17:59
  • 1
    Can you check [here](https://stackoverflow.com/questions/55906277/import-from-data-table-so-that-lintr-recognizes-it) – akrun Oct 12 '21 at 18:01
  • 2
    You might need to import `[` as well as `.`, perhaps `patterns` (not sure what `dtplyr` uses). If the well-maintained namespace is so critical (I'd think your users would not know or care), you could always *exclude* functions you don't want cluttering it. For that, use something like `#' @rawNamespace import(data.table, except=c(transpose))`. – r2evans Oct 12 '21 at 18:10
  • This does seem like an XY problem. Can you be more specific about the namespace issues you are concerned about when you do the simple `import data.table`? – Gregor Thomas Oct 12 '21 at 18:26
  • Thanks all for your help. After reading some more [documentation](https://cran.r-project.org/web/packages/data.table/vignettes/datatable-importing.html) I tried using `.datatable.aware = TRUE` inside the package and this seems to have done the trick. – wurli Oct 13 '21 at 07:39
  • Thanks for your question & answer. It would be better to post it as a proper answer, and accept it (no pbl to answer your own question). Then it will be easier to understand the question's solved status – Pierre Gramme Oct 27 '21 at 18:15
  • Thanks, you're very correct! Solution now posted as answer, and question also renamed to reflect the nature of the solution. – wurli Oct 27 '21 at 22:50

1 Answers1

2

The (documented) solution I found is to set .datatable.aware <- TRUE somewhere in the package source code. According to the documentation, if you're using data.table in a package without importing the whole thing, you should do this so that [.data.table() does not revert to calling [.data.frame(). From the docs:

...please define .datatable.aware = TRUE anywhere in your R source code (no need to export). This tells data.table that you as a package developer have designed your code to intentionally rely on data.table functionality even though it may not be obvious from inspecting your NAMESPACE file.

wurli
  • 2,314
  • 10
  • 17