2011-09-19 19 views
10

Sono nuovo di R.Come impostare il valore predefinito di uno slot come NULL in R?

sto cercando di definire una classe simile a un nodo della struttura, cioè, ha un nodo di sinistra e di destra del nodo, che dovrebbe essere della stessa classe del nodo padre . Così ho definire la classe come segue:

setClass('Node', representation=(left='Node',right='Node', ...)) 

voglio impostare il valore predefinito di nodo da NULL impostando un prototipo, ma R dice il seguente:

invalid class "Node" object: invalid object for slot "left" in class "bicluster": got class "NULL", should be or extend class "Node" 

Ma se I don' Specificare il valore predefinito come NULL, quindi il valore predefinito sarà un nodo ricorsivo di profondità 4, che ritengo sia uno spreco di risorse.

È la mia considerazione inutili o c'è un modo migliore per farlo?

risposta

7

questa è una risposta rivisto.

Le unioni di classe sono funky - inseriscono efficacemente una classe nel mezzo di una gerarchia esistente, quindi improvvisamente le cose che si estendono list ora estendono listOrNULL.

Invece mi piacerebbe creare una piccola gerarchia di classe che rappresenta un "albero" che può essere sia "vuoto" o "interno". La classe "Internal" avrà uno slot per contenere i dati (di tipo "ANY"), più i link sinistro e destro, che saranno elementi "Albero".

setClass("Tree") 

setClass("Empty", contains="Tree") 

setClass("Internal", contains="Tree", 
     representation=representation(elem="ANY", left="Tree", right="Tree"), 
     prototype=prototype(left=new("Empty"), right=new("Empty"))) 

scriverò un costruttore per il mio albero, con i metodi per la creazione di un albero vuoto, e un albero da un elemento più discendenti sinistro e destro.

setGeneric("Tree", function(elem, left, right) standardGeneric("Tree"), 
      signature="elem") 

setMethod(Tree, "missing", function(elem, left, right) new("Empty")) 

setMethod(Tree, "ANY", function(elem, left, right) { 
    new("Internal", elem=elem, left=left, right=right) 
}) 

Un funzionamento di base è quella di inserire un elemento x in un albero t

setGeneric("insert", function(x, t) standardGeneric("insert")) 

setMethod(insert, c("ANY", "Empty"), function(x, t) { 
    Tree(x, Tree(), Tree()) 
}) 

setMethod(insert, c("ANY", "Internal"), function(x, t) { 
    if (x < [email protected]) { 
     l <- insert(x, [email protected]) 
     r <- [email protected] 
    } else { 
     l <- [email protected] 
     r <- insert(x, [email protected]) 
    } 
    Tree([email protected], l, r) 
}) 

Un'altra operazione è quello di verificare l'appartenenza

setGeneric("member", function(x, t) standardGeneric("member")) 

setMethod(member, c("ANY", "Empty"), function(x, t) FALSE) 

setMethod(member, c("ANY", "Internal"), function(x, t) { 
    if (x < [email protected]) member(x, [email protected]) 
    else if ([email protected] < x) member(x, [email protected]) 
    else TRUE 
}) 

Una interessante, funzionale, proprietà di questa implementazione è che è persistente

> t <- Tree() 
> t1 <- insert(10, t) 
> t2 <- insert(5, t1) 
> t3 <- insert(7, t2) 
> t4 <- insert(15, t3) 
> which(sapply(1:20, member, t4)) 
[1] 5 7 10 15 
> which(sapply(1:20, member, t2)) 
[1] 5 10 

Questo non sta per essere efficace quando ci sono un sacco di aggiornamenti, a causa delle inefficienze della creazione di classe S4 e per la modifica di un albero (ad esempio, l'aggiunta di un nodo) copie tutti i nodi del percorso per il nuovo nodo. A different approach rappresenta l'albero come matrix di triple a sinistra, a destra, valore. L'implementazione S4 avrebbe comunque prestazioni scarse, perché gli aggiornamenti dell'istanza creerebbero nuove istanze, duplicando tutto. Quindi finirò in una classe di riferimento, con il valore "campi" (un vettore di ciò che l'albero dovrebbe contenere e uno matrix di relazioni sinistra e destra.

9

Un tempo era necessario utilizzare setClassUnion("listOrNULL",members=c("list", "NULL")) per ottenere un NULL in uno slot che è stato definito come una lista. Penso che ora sia una classe disponibile. Impossibile eseguire il test mentre l'installazione è incompleta, ma la definizione di un "NodeOrNull" di super classe potrebbe farti superare la barriera iniziale.

+1

Questo è l'approccio consigliato da Chambers in Software per Data Analysis (+1) – Henrik

+0

perfetto, grazie – RockScience

+0

Funziona perfettamente, molte grazie – eblondel

Problemi correlati