2015-11-18 6 views
9

Ho una domanda sull'ambito entro il quale vengono valutati i nomi delle funzioni nelle chiamate data.table::dcast (data.table versione 1.9.6, R 3.2.2).Nome funzione dinamico/privato in dcast.data.table

Vorrei creare il nome della funzione, ma questo non funziona.

Ecco che cosa ho provato:

library(data.table) 
DT <- data.table(value = c(1:10), 
       cat1 = c("a", "b", "a", "b", "a", "b", "a", "b", "c", "a"), 
       cat2 = c("x", "x", "x", "y", "y", "y", "y", "y", "y", "x")) 

Questo funziona bene:

result1 <- dcast.data.table(DT, cat1 ~ cat2, value.var = "value", fun = sum) 

ora faccio la mia propria funzione, che funziona anche:

f1 <- function(x) { 
    y <- sum(x)^2 
    return(y) 
} 
result2 <- dcast.data.table(DT, cat1 ~ cat2, value.var = "value", fun = f1) 

Qui faccio la stessa cosa, ma sto creando una funzione privata all'interno di una funzione. Tuttavia, questo non riesce con Error in eval(expr, envir, enclos) : could not find function "f2".

Se sostituisco f2 con f1 funziona e chiama f1. Sembra che stia guardando l'ambiente globale per valutare l'espressione fun = f2, e f2 esiste solo nello scope locale.

testFunction <- function(DT1) { 
    f2 <- function(x) { 
     y <- sum(x)^2 
     return(y) 
    } 
    r3 <- dcast.data.table(DT1,cat1 ~ cat2, value.var = "value", fun = f2) 
    return(r3) 
} 
result3 <- testFunction(DT) 

C'è un modo per aggirare questo? Quello che volevo veramente fare è rendere dinamico il nome della funzione f2, in modo che io passi dentro, diciamo "f3", e chiamerà la funzione privata f3.

avrei sperato che qualcosa di simile

functionName = "f3" 
r3 <- dcast.data.table(DT1, cat1 ~ cat2, value.var = "value", fun = get(functionName)) 

... otterrebbe me c'è, ma questo non sembra funzionare. Qualche idea?

+3

penso che questo è lo stesso di [bug # 1369] (https://github.com/Rdatatable/data.table/issues/1369) - non è ancora risolto. – Arun

+2

Bella prima domanda con un problema chiaramente descritto, dati giocattolo e codice che hai provato. Benvenuto in SO! E +1 ovviamente. – Henrik

risposta

3

In base alla segnalazione di bug, per il momento sono riuscito a risolvere il problema utilizzando un parametro denominato "fun.aggregate".

Grazie per avermi indicato.

Il codice seguente funziona e ottiene ciò di cui ho bisogno. Posso passare un nome di funzione preesistente come media o una funzione definita localmente.

testFunction <- function(DT1,functionName="mean") { 

    f2 <- function(x) { 
     y <- sum(x)^2 
     return(y) 
    } 

    fun.aggregate <- get(functionName) 

    r3 <- dcast.data.table(DT1,cat1~cat2,value.var="value",fun.aggregate=fun.aggregate) 
    return(r3) 
} 
result3 <- testFunction(DT,"mean") 
result4 <- testFunction(DT,"f2")