Search code examples
rvis.jsdiagrammer

Error passing an argument from a function to GrViz in DiagrammeR: "Object not found"


I am trying to create a function that outputs a graphic based on an input using diagrammeR::grViz, but the grViz function can't substitute the argument from my function. Here is a basic example:

library(DiagrammeR)

foo <- function(insert_text_here){
  text_to_show <- insert_text_here
  DiagrammeR::grViz("digraph {
    graph [layout = dot, rankdir = LR]

    node [shape = rectangle, fixedsize = true, width = 4.5, height = 1.5, fontname =   Helvetica, fontsize  = 20]
    rec1 [label = @@1]
    rec2 [label = b]
    # edge definitions with the node IDs
    rec1 -> rec2
    # from code

  }

  [1]: text_to_show
  ")
}

foo(insert_text_here = "hello")

Returns this error:

Error in eval(parse(text = split_references[i])): object "text_to_show" not found```.

If I define the variable text_to_show in my global environment outside of the function, it works perfectly without error:

text_to_show <- "hello"
foo(insert_text_here = "hello")

#success

So the issue comes when the input to GrViz is defined within by an argument to a function. Is there a way to work around this?

(this seems to be related to this issue: https://github.com/rich-iannone/DiagrammeR/issues/266)


Solution

  • The solution might be to use <<-:

    text_to_show <<- insert_text_here
    

    I get a diagram with two boxes the first of which is labelled "hello":

    enter image description here

    Generally the <<- function is deprecated, but I first tried to assign into the grViz environment and was told that its "environment is locked". Using <<- is equivalent to doing the assignment just prior to the function definition.

    EDIT: I don't know if it's better of more clear to use assign, but I found that you can make the assignment to the environment of foo, so this also succeeds as the first line of the body of foo:

    assign('text_to_show',  insert_text_here, envir=environment(foo))
    

    I worried that there might be something "too recursive" in that maneuver, but it appears that by the time that line gets evaluated there is a perfectly good foo in the search path.