2014-04-23 19 views
17

Sto riscontrando un problema nel far funzionare data.table nelle funzioni esportate in roxygen2.R data.table si interrompe nelle funzioni esportate

Ecco un semplice, funzione di falso in un file chiamato foo.R (si trova nella directory R del mio pacchetto) che usa data.table:

#' Data.table test function 
#' @export 
foo <- function() { 
    m <- data.table(c1 = c(1,2,3)) 
    print(is.data.table(m)) 
    m[,sum(c1)] 
} 

Se Copio e incollo questa funzione in R, questa funzione funziona bene:

> foo <- function() { 
+ m <- data.table(c1 = c(1,2,3)) 
+ print(is.data.table(m)) 
+ m[,sum(c1)] 
+ } 
> foo() 
[1] TRUE 
[1] 6 

Ma se ho semplicemente caricare la funzione esportata, R pensa che la data.table è un data.frame e si rompe:

> rm(foo) 
> load_all() 
Loading test_package 
> foo 
function() { 
    m <- data.table(c1 = c(1,2,3)) 
    print(is.data.table(m)) 
    m[,sum(c1)] 
} 
<environment: namespace:test_package> 
> foo() 
[1] TRUE 
Error in `[.data.frame`(x, i, j) : object 'c1' not found 

Che succede?

UPDATE

Grazie alla @GSee per l'aiuto. Sembra che questo sia in realtà un problema di devtools. Controlla il codice della riga di comando interattivo qui sotto.

Dopo il caricamento della libreria test_package, foo viene eseguito correttamente:

> foo 
function() 
{ 
    m <- data.table(c1 = c(1, 2, 3)) 
    print(is.data.table(m)) 
    m[, sum(c1)] 
} 
<environment: namespace:test_package> 
> foo() 
[1] TRUE 
[1] 6 

Esecuzione load_all() pause foo:

> load_all() 
Loading test_package 
> foo() 
[1] TRUE 
Error in `[.data.frame`(x, i, j) : object 'c1' not found 

In qualche modo source('R/foo.R') ravviva funzionalità pippo:

> source('R/foo.R') 
> foo 
function() { 
    m <- data.table(c1 = c(1,2,3)) 
    print(is.data.table(m)) 
    m[,sum(c1)] 
} 
> foo() 
[1] TRUE 
[1] 6 

E futuri inviti a load_all() non rompere foo ancora:

> load_all() 
Loading test_package 
> foo 
function() { 
    m <- data.table(c1 = c(1,2,3)) 
    print(is.data.table(m)) 
    m[,sum(c1)] 
} 
> foo() 
[1] TRUE 
[1] 6 

Inoltre, ho aggiornato a DevTools 1.5 e provato ad aggiungere .datatable.aware=TRUE, ma che non sembra di fare nulla.

+0

Sei sicuro che il 'foo' nel tuo pacchetto è esattamente lo stesso (cioè non hai lasciato la virgola tra' x ['e' col3'? – BrodieG

+0

Sono uguali. incollato la funzione dal file foo.R (mostrato sopra) nella riga di comando R. – kjmij

+0

Controlla 'yourpackagename :: foo' sulla riga di comando per assicurarti che siano davvero gli stessi. Solo perché il file che vedi sul tuo editor sembra che X non significhi che la funzione nel pacchetto caricato nella sessione R sia la stessa. – BrodieG

risposta

12

Il problema, come sottolineato da @GSee (sotto i commenti) sembra essere this issue ancora.

Al fine di scoprire se un pacchetto è data.table consapevoli, data.table chiama la funzione cedta(), che è:

> data.table:::cedta 
function (n = 2L) 
{ 
    te = topenv(parent.frame(n)) 
    if (!isNamespace(te)) 
     return(TRUE) 
    nsname = getNamespaceName(te) 
    ans = nsname == "data.table" || "data.table" %chin% names(getNamespaceImports(te)) || 
     "data.table" %chin% tryCatch(get(".Depends", paste("package", 
      nsname, sep = ":"), inherits = FALSE), error = function(e) NULL) || 
     (nsname == "utils" && exists("debugger.look", parent.frame(n + 
      1L))) || nsname %chin% cedta.override || identical(TRUE, 
     tryCatch(get(".datatable.aware", asNamespace(nsname), 
      inherits = FALSE), error = function(e) NULL)) 
    if (!ans && getOption("datatable.verbose")) 
     cat("cedta decided '", nsname, "' wasn't data.table aware\n", 
      sep = "") 
    ans 
} 
<bytecode: 0x7ff67b9ca190> 
<environment: namespace:data.table> 

Il controllo in questione qui è:

"data.table" %chin% get(".Depends", paste("package", nsname, sep=":"), inherits=FALSE) 

Quando un pacchetto dipende su data.table, il comando precedente deve restituire TRUE - ovvero, se è stato installato il pacchetto e tramite R CMD INSTALL e quindi caricato il pacchetto. Questo perché, quando si carica il pacchetto, R crea automaticamente una variabile ".Depends" nello spazio dei nomi. Se avete fatto:

ls("package:test", all=TRUE) 
# [1] ".Depends" "foo"  

Tuttavia, quando si esegue devtools:::load_all(), questa variabile non sembra essere impostato.

# new session + set path to package's dir 
devtools:::load_all() 
ls("package:test", all=TRUE) 
# [1] "foo" 

Quindi, cedta() non arriva a sapere che questo pacchetto davvero dipende su data.table. Tuttavia, quando si imposta manualmente .datatable.aware=TRUE, la linea:

identical(TRUE, get(".datatable.aware", asNamespace(nsname), inherits = FALSE)) 

Viene eseguito, che restituirà TRUE e quindi supera il problema. Ma il fatto che devtools non inserisca la variabile .Depends nello spazio dei nomi del pacchetto è ancora lì.

Tutto sommato, questo è veramente non un problema con data.table.