闪亮的 visNetwork 条件布局 - 绕过不兼容的选项

Shiny visNetwork conditional layout - getting around incompatible options

我正在构建一个 Shiny 应用程序来显示带有 visNetwork 的交互式网络,我想让用户可以在两个 igraph 布局之间进行选择。问题是一个布局所需的附加参数是另一个未使用的参数,我似乎无法有条件地摆脱它。

library(igraph)
library(shiny)
library(visNetwork)

# generate data
iGr <- make_graph("Meredith")
visGr <- toVisNetworkData(iGr)

# ui
ui <- fluidPage(
  # layout options
  radioButtons(
    inputId="grLayout",
    label="View in:",
    choices=list(
      "Graph layout"="layout_with_graphopt",
      "Ellipse layout"="layout_in_circle"
    ),
    selected="layout_with_graphopt"
  ),
  visNetworkOutput("netPlot")
)

# server
server <- function(input, output){
  output$netPlot <- renderVisNetwork({
    visNetwork(visGr$nodes, visGr$edges) %>%
      visIgraphLayout(physics=FALSE, type="square", layout=input$grLayout,
                      charge=0.1 # <- here's my problem
                      )
  })  
}

shinyApp(ui=ui, server=server)

我需要 layout_with_graphopt 选项的 charge 参数和我的真实数据以使可视化可读,但它会抛出一个“未使用的参数(费用 = 0.1)”错误 layout_in_circle选项。我已经尝试了两种变体但没有成功。

这个根本不会 运行 并抛出 'argument "graph" is missing, with no default' 错误:

  output$netPlot <- renderVisNetwork({
    visNetwork(visGr$nodes, visGr$edges) %>%
      {if (input$grLayout=="layout_with_graphopt") {
        visIgraphLayout(physics=FALSE, type="square", layout=input$grLayout,
                        charge=0.1)
      } else {
        visIgraphLayout(physics=FALSE, type="square", layout=input$grLayout)
      }}
  })

此选项为 layout_in_circle 选项抛出“未使用的参数 (charge = NULL)”错误。 (如果我尝试 NA,我会得到类似的结果):

  output$netPlot <- renderVisNetwork({
    chargeVal <- if (input$grLayout=="layout_with_graphopt") {0.1} else {NULL}
    visNetwork(visGr$nodes, visGr$edges) %>%
      visIgraphLayout(physics=FALSE, type="square", layout=input$grLayout,
                      charge=chargeVal)
  })

我宁愿不对整个 renderVisNetwork 块做一个 if else 因为真正的块很长,有很多花哨的东西,而且 charge 论点将是它们之间的唯一区别。

我明白了。诀窍是将 除了 visIgraphLayout 行之外的所有内容都粘贴到 visNetwork 对象中,然后将 visIgraphLayout 的条件版本传递到它的背面:

  output$netPlot <- renderVisNetwork({
    plot1 <- visNetwork(visGr$nodes, visGr$edges)
    # can add whatever other bells and whistles needed before if/else if
    # conditional layout:
    if (input$grLayout=="layout_with_graphopt"){
      plot2 <- plot1 %>%
        visIgraphLayout(physics=FALSE, type="square", layout=input$grLayout,
                        charge=0.1)
    } else if (input$grLayout=="layout_in_circle") {
      plot2 <- plot1 %>%
        visIgraphLayout(physics=FALSE, type="square", layout=input$grLayout)
    }
    return(plot2)
  })