简体   繁体   English

在R flexdashboard中使用闪亮的模块

[英]Using shiny modules in R flexdashboard

I tried to use flexdashboard to make interactive vizualisation of word embeddings results, but I don't get the logic behind the use of shiny modules. 我尝试使用flexdashboard使单词嵌入的结果交互式化,但是我没有得到使用闪亮模块背后的逻辑。

In my Rmd dashboard, after loading the needed libraries, I first load the 3 models I want to deal with: 在Rmd仪表板中,加载所需的库之后,我首先加载了要处理的3个模型:

---
title: "Embedding Explorer"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: fill
    runtime: shiny
---

```{r setup, include=FALSE}
library(flexdashboard)
library(wordVectors)
library(plotly)
library(shiny)
library(shinyjs)
```

```{r global, include=FALSE}
model_1 = wordVectors::read.vectors('./models/word_embeddings_1.bin')
model_2 = wordVectors::read.vectors('./models/word_embeddings_2.bin')
model_3 = wordVectors::read.vectors('./models/word_embeddings_3.bin')
```

Then I would like each component of my dashboard to load a specific module. 然后,我希望仪表板的每个组件都加载特定的模块。 In the sidebar for instance, I want to display a selectInput object to select one of the models. 例如,在边栏中,我想显示一个selectInput对象以选择模型之一。 To do so, I have coded a R script module Models.R: 为此,我编写了一个R脚本模块Models.R:

# UI function
selectModelInput <- function(id) {
  ns <- NS(id)
  tagList(
  selectInput(ns("target_model"),label="Target model",c("gloVe","Word2Vec","Fasttext"))
)
}

# Server function
selectModel <- function(input, output,session) {
   observeEvent(input$target_model,{
     if (input$target_model=="gloVe"){
       model = model_1
    }else if (input$target_model=="Word2Vec"){
      model = model_2
    }else if (input$target_model=="Fasttext"){
      model = model_3
    }
output$model <- model #add an output element
    })
}

Thus, I call this module in my Rmd file: 因此,我在Rmd文件中调用此模块:

```{r sidepanel}
# include the module
source("./modules/Models.R")

# call the module
selectModelInput("mod")
model <- callModule(selectModel,"mod") #add model in variable

renderText("Vocabulary size:")
renderPrint(nrow(model))
renderText("Embeddings dim:")
renderPrint(ncol(model))

```

Doing so, I have an error message stating that 'model' object does not exist. 这样做,我收到一条错误消息,指出“模型”对象不存在。 Maybe the problem is that the module doesn't have access to the model_x from the global part? 也许问题在于模块无法从全局部分访问model_x? Or do I miss something allowing to save the 'model' object somewhere? 还是我错过了一些允许将“模型”对象保存在某处的东西? By the way, I don't really understand the call module behavior (especially, what is the role of the id argument "mod" or whatever?). 顺便说一句,我不太了解调用模块的行为(尤其是id参数“ mod”的作用是什么?)。

I precise that I have already developed a classical Shiny app which works perfectly (server / ui, no modules used), but I want to make the vizualisation more "professional"... 我想我已经开发了一个完美运行的经典Shiny应用程序(服务器/用户界面,未使用任何模块),但我想让Vizualization更加“专业” ...

Thanks for any help! 谢谢你的帮助!

UPDATE: By curiosity, I have printed the "model" output: 更新:出于好奇,我打印了“模型”输出:

selectModelInput("mod")
model <- callModule(selectModel,"mod")
renderPrint(model)

And this is the result: 结果如下:

<Observer>
  Public:
.autoDestroy: TRUE
.autoDestroyHandle: function () 
.createContext: function () 
.ctx: environment
.destroyed: FALSE
.domain: session_proxy
.execCount: 2
.func: function (...) 
.invalidateCallbacks: list
.label: observeEvent(input$target_model)
.onDomainEnded: function () 
.onResume: function () 
.prevId: 13
.priority: 0
.suspended: FALSE
clone: function (deep = FALSE) 
destroy: function () 
initialize: function (observerFunc, label, suspended = FALSE, priority =  0, 
onInvalidate: function (callback) 
resume: function () 
run: function () 
self: Observer, R6
setAutoDestroy: function (autoDestroy) 
setPriority: function (priority = 0) 
suspend: function () 

It seems that 'model' variable is not what is expected (ie model_1, model_2 or model_3)... Why? 似乎'model'变量不是预期的值(即model_1,model_2或model_3)...为什么?

The problem is that the environment inside the module is basically treated like it would be in a function. 问题在于,基本上像对待函数一样对待模块内部的环境。 Consider the following code 考虑以下代码

fun <- function(x) {
  result <- x + 1
  result ## return the result
}

fun(2)

result
#> Error: object 'result' not found

This above issue can be resolved by saving the return value of the function in a variable 可以通过将函数的返回值保存在变量中来解决上述问题

res <- fun(2)
res
#> 3

You need to apply the same logic to your modules: everything that comes out of the module has to be returned by the module-server-function, which is selectModel in your case. 您需要对模块应用相同的逻辑:模块中的所有内容都必须由module-server-function返回,在本例中为selectModel

model <- callModule(selectModel,"mod")

If that where not the case, the namespacing would make no sense at all since several modules would write to the same variable at the same time. 如果不是这种情况,则命名空间根本没有任何意义,因为几个模块会同时写入同一变量。

Regading your more general question "What does callModule do?". 关于您的更笼统的问题“ callModule做什么?”。 Basically it makes it so all input- and output-ids are prefixed. 基本上,它使所有输入和输出ID都带有前缀。 That means that if input$target_model is used inside a module with id mod , this will actually get input[["mod-target_model"]] . 这意味着,如果在具有id mod的模块内部使用input$target_model ,则实际上将获得input[["mod-target_model"]] You can think of this as creating a "folder" for your input and output ids which makes sure your ids do not collide with one another. 您可以认为这是为输入和输出ID创建一个“文件夹”,以确保您的ID不会相互冲突。 In this analogy, mod would be the folder name and target_model would be a file inside that folder. 以此类推, mod将是文件夹名称,而target_model将是该文件夹内的文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM