分配reactiveValues()创建的空数据框 [英] on assignment of reactiveValues() empty dataframe created

查看:75
本文介绍了分配reactiveValues()创建的空数据框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可重现的示例:

server.R

library(shiny)

shinyServer( function(input, output, session) {

    myDf <- reactiveValues(myData = NULL)

    problematicDf <- reactiveValues(test = NULL)

    observeEvent(input$myButton, {
            myDf$myData <- df
    })


    observe({
            output$myTestUi <- renderUI({
                    selectInput(inputId = 'mySelection', 
                                label = 'Selection', 
                                choices = levels(myDf$myData$z),
                                multiple = T,
                                selected = c(levels(myDf$myData$z)[1])
                    )
            })
    })


    observe({
            problematicDf$test <- subset(myDf$myData, ((myDf$myData$z %in% input$mySelection)))
    })


    observe({
            str(problematicDf$test)
    })

    observe({
            as.matrix(x = problematicDf$test)
    })
})

ui.R

library(shiny)

shinyUI( bootstrapPage( 

    h3("Push the button"),
    actionButton(inputId = "myButton",
                 label = "clickMe"),

    h4("Split Merkmal"),
    uiOutput("myTestUi")

))

global.R

df <- data.frame(x = 1:10, y = 10:1, z = letters[1:10])
df$z <- as.factor(df$z)

这给了我:

NULL
[1] "NULL"
NULL
Warning: Unhandled error in observer: 'data' must be of a vector type, was 'NULL'
observe({
    as.matrix(x = problematicDf$test)
})

只看

observe({
  str(problematicDf$test)
  print(class(problematicDf$test))
  print(problematicDf$test$z)
})

点击action Button后,没有as.matrix,我得到:

after clicking on the action Button, without the as.matrix, I get:

NULL
[1] "NULL"
NULL
'data.frame':   0 obs. of  3 variables:
 $ x: int 
 $ y: int 
 $ z: Factor w/ 10 levels "a","b","c","d",..: 
[1] "data.frame"
factor(0)
Levels: a b c d e f g h i j
'data.frame':   1 obs. of  3 variables:
 $ x: int 1
 $ y: int 10
 $ z: Factor w/ 10 levels "a","b","c","d",..: 1
[1] "data.frame"
[1] a
Levels: a b c d e f g h i j

这是有问题的.正如你所看到的,它首先创建了一个 df,它是一种空的,带有占位符,class = NULL.然后,它填补了这个.然而,似乎其他 reactive 函数,等待 problematicDf$test 被创建,尽快作为空的 df 已创建(使用 class = NULL).他们之后不再更新.它们仅在做出另一个选择时更新.这会导致(在我的情况下)程序崩溃,因为我需要使用如此创建的 data.frame 继续工作和设置子集等.

That is problematic. As you can see it creates first a df which is sort of empty, with placeholders, of class = NULL. And then, it fills this. However, it seems that other reactive functions, waiting for the problematicDf$test to be created kick in as soon as the empty df is created (with class = NULL). They do not update afterwards anymore. They only update when another selection is made. This causes (in my case) the program to crash since I need to keep on working and subsetting etc. with the so created data.frame.

如何处理?!我可以包含一个 if else 并检查 class = NULL.但在我看来,这是一种不雅的方式.

How to handle this?! I could include an if else and check for class = NULL. But it seems to me that this is an unelegant way.

推荐答案

是否有理由将 myDf 初始化为 NULL?如果没有,您可以轻松解决在初始化时分配 df 的问题.如果您这样做,您的代码也不需要按钮.

Is there a reason for you to initialize myDf as NULL? If not, you could easily solve your problem assigning df at it's initialization. If you do so, your code won't need the button either.

并且您不应该在 observe 中声明您的 renderUI.每当您选择所选项目时,observe 就会被激活,它会将您的 selectInput 设置为其初始状态(仅选择项目a").

And you shouldn't declare your renderUI inside observe. Whenever you chance the selected item, the observe is activated and it will set your selectInput to it's initial state (with only item 'a' selected).

编辑 1

# server.R

shinyServer( function(input, output, session) {
   # initialize myDf$myData with df and problematicDf as NULL
   myDf <- reactiveValues(myData = df)
   problematicDf <- reactiveValues(test = NULL)

   # you don't have to observe here. once the selectInput 
   # has been created, you can (un)select how many choices you want
   output$myTestUi <- renderUI({
       selectInput(inputId = 'myTestUi', 
                   label = 'Selection', 
                   choices = levels(myDf$myData$z),
                   multiple = T,
                   # this line determines that ONLY the first item on 
                   # c(levels(myDf$myData$z)[1] is selected on the selectInput initialization!
                   selected = c(levels(myDf$myData$z)[1])
       )
   })

   observe({
       problematicDf$test <- subset(myDf$myData, 
                             (myDf$myData$z %in% input$myTestUi))
   })

   observeEvent(input$myButton, {
       # the code in here will only run when the button is pushed!
       print("you should only put things here that you want to be flushed on the button being clicked!")
   })

})

编辑 2

因此,将 myDf$myData 初始化为 NULL 并在 observeEvent 中分配 df.

So do initialize myDf$myData as NULL and assign df inside the observeEvent.

renderUI 将作为一个 selectInput 开始,没有任何选择,但只要按下按钮,选择就会分配给它.

The renderUI will begin as a selectInput without any choices, but as soon as the button is pushed, choices will be assigned to it.

您提到了一些 reactive 函数在数据仍然为 NULL 时会崩溃.有很多方法可以解决这个问题.一种方法是使用您提到的 if(is.null(myDf$myData)) return(NULL) .可能不是最优雅的方式,但通常工作得很好.其他方式可能包括 isolateobserveEvent(默认情况下它不会对 NULL 输入做出反应).这取决于您的应用程序作为一个整体如何工作.

You mention some reactive functions that crash when the data is still NULL. There are lots of ways to deal with that. One way is to just use a if(is.null(myDf$myData)) return(NULL) as you mentioned. Might not be the most elegant way but usually works just fine. Other ways may include isolate or an observeEvent (it doesn't react to NULL inputs by default). It depends on how your app work as a whole.

但您似乎还没有完全理解反应性和其他闪亮元素的工作原理.尝试阅读 rstudio 文章,特别是反应式编程"部分(http://shiny.rstudio.com/articles/).

But it seems you haven't fully understood how reactivity and other shiny elements work. Try reading the rstudio articles, specially the 'reactive programming' part (http://shiny.rstudio.com/articles/).

这篇关于分配reactiveValues()创建的空数据框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆