我无法让输入滑块在 Shiny 的应用程序中呈现在 ggvis 图中。绘图在没有输入滑块的情况下渲染良好,但在添加 Shiny 后会引发此错误:

Listening on http://xxxxxxxxxxxxxx
Error in eval(expr, envir, enclos) : could not find function "compdat" 

服务器.R:

    library(shiny)
    library(ggvis)

    data<-data.frame(var1=rnorm(30,5,2.3),var2=rbeta(30,1.5,.8),var3=rnorm(30,10,2.5))

    shinyServer(function(input, output,session) {

    compdat<-reactive({data[, c(input$xInp,input$yInp)]})

    vis1 <-reactive({

      compdat %>% ggvis(x= ~compdat()[,1],y= ~compdat()[,2]) %>%
       layer_points(fill:="red") %>% layer_smooths(span=input_slider(.1,1,id="scores_ui"))

    })

    vis1 %>% bind_shiny("scores",controls_id="scores_ui")

    vis2<-reactive({

      compdat %>% ggvis(x= ~compdat()[,1],y= ~compdat()[,2]) %>%
       layer_points(fill:="red") %>% ayer_smooths(span=input_slider(.1,1,id="loadings_ui"))

    })

    vis2 %>% bind_shiny("loadings",controls_id="loadings_ui")

    })

用户界面:


    shinyUI(fluidPage(

     title="PCA Explorer",
     h2("Principal Component Explorer"),

     fluidRow(
      column(6,ggvisOutput("scores"),
               uiOutput("scores_ui")),
      column(6,ggvisOutput("loadings"),
               uiOutput("loadings_ui"))
     ),

     br(),

     fluidRow(
      column(6,h3("Component Selection"),selectInput('xInp',"X Variable",names(data)),
       selectInput('yInp',"Y Variable",names(data),selected=names(data)[[2]])),
      column(6,h3("Summary of Selected Data Points"),verbatimTextOutput("diagn"))

      )
    ))

关于如何让滑块渲染的任何见解都会很棒。我花了相当多的时间来挖掘这个问题。提前致谢

最佳答案

在此 Movie Explorer example 中可以找到一个很好的示例,演示如何使用 selectizeInput 自定义 X/Y 轴变量。

但是,将 ggvis() 函数包装在响应式(Reactive)环境中具有突出的缺点(或错误),即一旦您更改 input$xInp$input$yInplayer_smooths() 就会停止对您的滑块输入使用react。

您的代码的另一个潜在问题是 dataui.R 不可见。
您可能想要创建一个包含 global.R 对象的 data 文件。

下面我将介绍如何通过选择 X/Y 变量与 ggvis 图进行交互的两种方法。您可以在 server.R 中找到它们。

全局R

data <- data.frame(var1=rnorm(30,5,2.3),
                 var2=rbeta(30,1.5,.8),
                 var3=rnorm(30,10,2.5))

用户界面
library(shiny)

shinyUI(fluidPage(

    title="PCA Explorer",
    h2("Principal Component Explorer"),

    fluidRow(
        column(6,
            ggvisOutput("scores"),
            uiOutput("scores_ui")),
        column(6,
            ggvisOutput("loadings"),
            uiOutput("loadings_ui"))
    ),

    br(),

    fluidRow(
        column(6,
            h3("Component Selection"),
            selectInput('xInp',"X Variable", choices=names(data),
                        selected=names(data)[[1]]),
            selectInput('yInp',"Y Variable", choices=names(data),
                        selected=names(data)[[2]])
        ),
        column(6,
            h3("Summary of Selected Data Points"),
            verbatimTextOutput("diagn"))
    )
))

服务器
library(shiny)
library(ggvis)

shinyServer(function(input, output,session) {
    # Approach 1: regenerate a compdat object once the input changes
    # rename the X/Y variables to fixed names.
    compdat <- reactive({
        x <- data[, c(input$xInp, input$yInp)]
        names(x) <- c("x", "y")
        x
    })

    # NOTE that you use compdat here instead of compdat()
    compdat %>% ggvis(x=~x, y=~y) %>%
        layer_points(fill:="red") %>%
        layer_smooths(span=input_slider(.1,1)) %>%
        bind_shiny("scores", controls_id="scores_ui")

    # Approach 2: wrap ggvis in a reactive environment
    # This however, would stop to react to slider input
    # once input$xInp or input$yInp changes.
    vis2 <- reactive({
        xvar <- prop("x", as.symbol(input$xInp))
        yvar <- prop("y", as.symbol(input$yInp))

        data %>% ggvis(x=xvar, y=yvar) %>%
        layer_points(fill:="red") %>%
        layer_smooths(span=input_slider(.1,1))
    })

    vis2 %>% bind_shiny("loadings", controls_id="loadings_ui")
})

这两种方法都应该有效(好吧,几乎)。但是等等,您可能会看到平滑层在您更改 X/Y 变量后停止响应您的滑块更改。

要解决此问题,请考虑以下解决方案。

使用方法 2 解决问题

我之前提到的错误可以通过在 sliderInput 中创建一个 ui.R 来修复。

用户界面
library(shiny)

shinyUI(fluidPage(

    title="PCA Explorer",
    h2("Principal Component Explorer"),

    fluidRow(
        column(6,
            ggvisOutput("scores"),
            uiOutput("scores_ui")
        ),
        column(6,
            ggvisOutput("loadings"),
            uiOutput("loadings_ui"),
            # Create a slider by Shiny, instead of by ggvis.
            sliderInput('smooth_span',
                        h5("Smoothing span for plot 2"),
                        .1, 1, value=0.5)
        )
    ),

    br(),

    fluidRow(
        column(6,
            h3("Component Selection"),
            selectInput('xInp',"X Variable", choices=names(data),
                        selected=names(data)[[1]]),
            selectInput('yInp',"Y Variable", choices=names(data),
                        selected=names(data)[[2]])
        ),
        column(6,
            h3("Summary of Selected Data Points"),
            verbatimTextOutput("diagn"))
    )
))

服务器
library(shiny)
library(ggvis)

shinyServer(function(input, output,session) {
    # Approach 1: regenerate a compdat object once the input changes
    # rename the X/Y variables to fixed names.
    compdat <- reactive({
        x <- data[, c(input$xInp, input$yInp)]
        names(x) <- c("x", "y")
        x
    })

    # NOTE that you use compdat here instead of compdat()
    compdat %>% ggvis(x=~x, y=~y) %>%
        layer_points(fill:="red") %>%
        layer_smooths(span=input_slider(.1,1)) %>%
        bind_shiny("scores", controls_id="scores_ui")

    # Approach 2: wrap ggvis in a reactive environment
    # This however, would stop to react to slider input
    # once input$xInp or input$yInp changes.
    vis2 <- reactive({
        xvar <- prop("x", as.symbol(input$xInp))
        yvar <- prop("y", as.symbol(input$yInp))
        smooth.span <- input$smooth_span

        data %>% ggvis(x=xvar, y=yvar) %>%
        layer_points(fill:="red") %>%
        # FIXED: use the value from the input object, instead of a input_slider
        layer_smooths(span=smooth.span)
    })

    vis2 %>% bind_shiny("loadings", controls_id="loadings_ui")
})

最后的话

ggvis 包装到响应式环境中有一些缺点:
  • 性能下降:因为一旦相关输入变量发生变化,整个图形需要重新绘制。
  • 缺少过渡动画:因为整个图形都被重绘,所以你看不到方法 1 中的漂亮过渡效果。

  • 但是,它确实有几个优点:
  • 更高的灵活性:AFAIK,如果您想动态更改 X-Y 轴标签(例如,取决于您的 ggvis ),则将 input$xInp 包装在 react 环境中是目前 唯一的 方式。由于 ggvis 只计算一次数据并将数据绑定(bind)到 ggvis 对象,因此对轴标签所做的更改不会实时反射(reflect)。然而,因为在 react 环境中包装 ggvis 会导致整个图形重绘,所以标签也会在重绘中更新。
  • 关于以 Shiny 的方式渲染 ggvis 控件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25088248/

    10-12 19:42