2013-10-08 91 views
5

Sto tentando di utilizzare bnlearnpackage per calcolare le probabilità condizionali e sto riscontrando un problema quando si utilizza la funzione "cpquery" all'interno di un ciclo. Ho creato un esempio, mostrato di seguito, utilizzando i dati inclusi nel pacchetto. Quando si utilizza la funzione cpquery in un ciclo, una variabile creata nel ciclo ("evi" nell'esempio) non viene riconosciuta dalla funzione. Ho ricevuto l'errore:Utilizzo della funzione bnlearn "cpquery" all'interno di un loop

Error in parse(text = evi) : object 'evi' not found 

Le fasi di creazione di "evi" si basano su esempi forniti dall'autore.

Qualsiasi aiuto che potresti fornire sarebbe fantastico. Sono disperato di trovare un modo in cui posso applicare la funzione cpquery per un gran numero di osservazioni.

library(bnlearn) 
data(learning.test) 
fitted = bn.fit(hc(learning.test), learning.test) 

bn.function <- function(network, evidence_data) { 
    a <- NULL 
    b <- nrow(evidence_data) 
    for (i in 1:b) { 
    evi <- paste("(", names(evidence_data), "=='", 
       sapply(evidence_data[i,], as.character), "')", 
       sep = "", collapse = " & ") 
    a[i] <- cpquery(network, (C=='c'), eval(parse(text=evi))) 
    } 
    return(a) 
} 

test <- bn.function(fitted, learning.test) 

Grazie in anticipo!

+1

Sono stato in contatto con l'autore del pacchetto bnlearn e sembra che l'errore che sto ricevendo sia dovuto a un problema di scoping con la funzione cpquery. Questo è evidente quando sono in grado di far funzionare correttamente la funzione cpquery in un ciclo for che è costruito _outside_ di una funzione definita dall'utente, ma ha l'errore quando lo stesso ciclo viene utilizzato _inside_ di un utente definito funzione. –

risposta

0

per evitare il problema di scoping, è possibile posticipare la chiamata a eval e farlo all'interno la funzione cpquery. Se si passa direttamente evi (la variabile di carattere) a cpquery e quindi lo si analizza all'interno della definizione, la catena di ambienti diventa spostata e cpquery avrà accesso a evi.

È possibile utilizzare m.cpquery <- edit(cpqurey) a sborsare la propria versione della funzione e inserire la seguente riga al suo inizio:

evidence = parse(text = evidence) 

e quindi salvare la nuova funzione. Così il titolo di m.cpquery sarà simile:

> m.cpquery 
function (fitted, event, evidence, cluster = NULL, method = "ls", 
    ..., debug = FALSE) 
{ 
    evidence = parse(text = evidence) 
    check.fit(fitted) 
    check.logical(debug) 
... 

Ora è possibile utilizzare m.cpquery nella propria funzione come prima, tranne passeremo la variabile carattere pianura ad esso:

a[i] <- m.cpquery(network, (C=='c'), evi) 

Si noti che nella prima riga di m.cpquery, abbiamo solo analizzato la variabile del carattere di prova e non abbiamo chiamato eval su di esso. cpquery è un front-end a conditional.probability.query (vedere here) e ci affidiamo alla chiamata successiva di conditional.probability.query allo eval.

Devo dire che questa è una brutta soluzione. E funziona solo se si utilizza il campionamento logico (method='ls'). Ma se si desidera utilizzare la probabilità che ponderazione, la funzione genera un errore. Non ho controllato se l'iniezione di un'espressione eval prima che venga chiamata comporterebbe un caos di errori successivi che portano all'inferno.