0

I have a question concerning environments in evaluating expressions. Specifically, I have a function bnlearn::cpdist that takes a logical expression as an argument. I wish to use a variable to specify that argument, so I wish to use eval(parse(text = string)). But in the case this is happening within the environment of a larger function, the eval function can't find the variable "string", despite it having been defined in that environment. I am confused. Here is the code the reproduces the problem.

# The function is from the bnlearn package, which handles Bayesian networks
library(bnlearn)
#Example data
data(learning.test)
#Fitting a model
fitted = bn.fit(hc(learning.test), learning.test)
#The function in question generates samples from the PDF of one node given the values of others.  
posterior = cpdist(fitted, "D", (A == "a" & C == "b")) #Notice the awkward logical statement arg
prop.table(table(posterior))

#I want to use character variables instead of the logical statement.
#If I use parse and eval to specify the logical statement I have no issues.
evidence.nodes <- c("A", "C")
evidence.values <- c("a", "b")
ev <- paste("(", evidence.nodes, "=='",
                  sapply(evidence.values, as.character), "')",
                  sep = "", collapse = " & ")
posterior <- cpdist(fitted, "D", eval(parse(text = ev)))


#But what I want to do is apply do this from within a function
getPosterior <- function(fitted, target, ev.nodes, ev.values){
    ev <- paste("(", ev.nodes, "=='",
                  sapply(ev.values, as.character), "')",
                  sep = "", collapse = " & ")

     posterior <- cpdist(fitted, "D", eval(parse(text = ev)))
     prop.table(table(posterior))
}

#Here is where the problem lies.  The following works if "ev" is already defined as it was above.  However, if you remove ev from the global environment, then it fails.  I do not understand why it cannot find the ev object defined within the function's environment.

new.data <- data.frame(A = c("a", "b", "a", "b"), C = c("a", "a", "b", "b"))    
rm(ev)
for(i in 1:nrow(new.data)){
    print(getPosterior(fitted, "D", names(new.data), new.data[i, ]))    
}   
Count Zero
  • 630
  • 1
  • 6
  • 15
  • There are lots of issues here, but first off, the error is coming from `parse()` not `eval()`. If you fix that then you get another error, this time from `eval()`. Where or in what object do you want the expression `ev` (from `getPosterior()`) to be evaluated? I.e. where should it find `A` etc. – Gavin Simpson Nov 25 '13 at 18:25
  • You ask a simple question about variable scope in eval() but you provide overly complicated and irrelevant code ... (-1, sorry) – Raffael Nov 25 '13 at 18:51
  • I voted to close your [earlier version](http://stackoverflow.com/q/20183230/324364) of this question, since this one is actually an improvement (IMHO). – joran Nov 25 '13 at 19:10
  • Thanks for the comments. I gave the code because it seems people want to be able to reproduce the error. What I don't get is that the code works eval() can find the "ev" object when its defined in the global environment but not when it is defined within the function. – Count Zero Nov 25 '13 at 19:22

1 Answers1

1

I had an issue like this. I solved it with super assignation on the variable that was not found in my function.

var <<- 5