Home > Blockchain >  accessing unexported function in data.table
accessing unexported function in data.table

Time:09-11

I want to run a moving average (preferably witch custom weights) on a data.table object. frollmean is very fast compared to frollapply (especially) and even TTR::EMA (which does not allow custom weights but only wilder=T/F)--performance comparison at the end. I tried to use data.table:::froll (which frollmean uses and is not exported). It's first argument must be the (character) name of the function (for frollmean it is mean).

data.table:::froll('f.roll', x$c, 10)
Error in data.table:::froll("f.roll", x$c, 10) : 
  Internal error: invalid fun argument in rolling function, should have been caught before. please report to data.table issue tracker.

I tried to access the data.table package as an environment:

e.dt <- as.environment('package:data.table')
e.dt$froll <- data.table:::froll
Error in e.dt$froll <- data.table:::froll (from c.ta.R#287) : 
  cannot add bindings to a locked environment
e.dt2 <- new.env(parent=e.dt)
e.dt2$froll <- data.table:::froll
e.dt2$froll('f.roll', top.., n, na.rm=T)
Error in e.dt2$froll("f.roll", x$c, n, na.rm = T) : 
  Internal error: invalid fun argument in rolling function, should have been caught before. please report to data.table issue tracker.

I also tried attaching my custom function f.roll to e.dt2:

e.dt2$f.roll <- f.roll
e.dt2$froll('f.roll', top.., n, na.rm=T)
Error in e.dt2$froll("f.roll", top.., n, na.rm = T) : 
  Internal error: invalid fun argument in rolling function, should have been caught before. please report to data.table issue tracker.

froll calls a C function (CfrollfunR):

data.table:::froll
function (fun, x, n, fill = NA, algo = c("fast", "exact"), align = c("right", 
    "left", "center"), na.rm = FALSE, hasNA = NA, adaptive = FALSE) 
{
    stopifnot(!missing(fun), is.character(fun), length(fun) == 
        1L, !is.na(fun))
    algo = match.arg(algo)
    align = match.arg(align)
    ans = .Call(CfrollfunR, fun, x, n, fill, algo, align, na.rm, 
        hasNA, adaptive)
    ans
}
<bytecode: 0x0000000013738b40>
<environment: namespace:data.table>

data.table:::CfrollfunR
$name
[1] "CfrollfunR"

$address
<pointer: 0x000000001ef93e80>
attr(,"class")
[1] "RegisteredNativeSymbol"

$dll
DLL name: datatable
Filename: C:/bin/cygwin/cygwin64/home/Adi/R/win-library/4.0/data.table/libs/x64/datatable.dll
Dynamic lookup: FALSE

$numParameters
[1] -1

attr(,"class")
[1] "CallRoutine"      "NativeSymbolInfo"

However, while my custom function f.roll doesnt' work, mean as the first parameter works:

tail(e.dt2$froll('mean', x$c, 10, na.rm=T))
[1] 43.506 43.148 42.855 42.548 42.331 42.200

I inspected the data.table DLL C:\bin\cygwin\cygwin64\home\Adi\R\win-library\4.0\data.table\libs\x64\datatable.dll (using DLL Export Viewer) but it doesn't show any function called mean. data.table package also doesn't have any mean function (either exported or not exported).

data.table:::mean
Error in get(name, envir = asNamespace(pkg), inherits = FALSE) : 
  object 'mean' not found
data.table::mean
Error: 'mean' is not an exported object from 'namespace:data.table'

Any suggestion would be greatly appreciated.

PS Here's the performance comparison from microbenchmark for reference:

## Unit: milliseconds
##        expr         min          lq        mean      median          uq         max neval
##  frollapply 131736.6469 131736.6469 131736.6469 131736.6469 131736.6469 131736.6469     1
##         EMA    262.9931    262.9931    262.9931    262.9931    262.9931    262.9931     1
##   frollmean     97.0388     97.0388     97.0388     97.0388     97.0388     97.0388     1

PS Since froll isn't a solution to my problem (as @Waldi points out) I'm looking for an alternate solution but I left this as is and asked a separate, new question: fast way to calculate moving average/rolling function which allows custom weights

CodePudding user response:

C source code of froll, shows that this internal function is only designed for mean or sum, the error isn't linked to the environment :

enum {MEAN, SUM} sfun;
  if (!strcmp(CHAR(STRING_ELT(fun, 0)), "mean")) {
    sfun = MEAN;
  } else if (!strcmp(CHAR(STRING_ELT(fun, 0)), "sum")) {
    sfun = SUM;
  } else {
    error(_("Internal error: invalid %s argument in %s function should have been caught earlier. Please report to the data.table issue tracker."), "fun", "rolling"); // # nocov
  }
  • Related