2017-04-22 34 views
2

我有一個我不明白的Shiny應用程序的問題。我認爲這是一個反應性物體的概念問題,但我不確定。在Shiny應用程序中創建動態標籤集給ggploty上的錯誤

該應用程序基於使用uiOutput的數據集的列名稱創建一個選項卡。然後我在Observe中動態創建相應的plotlyOutput。

問題是,當我更改數據集時,它們的列也會更改它們的名稱,並且似乎應用程序會記住最後一個入口,並嘗試使用不存在的數據呈現對象。

的結果是這樣一個警告:在UseMethod錯誤::

警告應用於類「NULL」堆棧跟蹤(最內第一)的目的關於「ggplotly」 沒有適用的方法: 79:ggplotly 78:FUNC 77:origRenderFunc 76:輸出$ tabPlot_a1 1:runApp

我創建了一個閃亮的應用程序來重新創建錯誤,只要打開它,去爲製表2然後將「前綴」更改爲「b」。

選項卡更改,但它會給出警告。

任何提示發生了什麼?

代碼:

library("shiny") 
library("shinydashboard") 
library("plotly") 
library("ggplot2") 

shinyApp(
    ui=shinyUI(dashboardPage(skin = "blue", 
          dashboardHeader(title = "Dashboard"), 
          dashboardSidebar(
          textInput("prefix", label = "Columns prefix", value = "a") 
          ), 
          dashboardBody(
          tabBox(
           tabPanel("Tab 1", "This is tab number 1", tableOutput("tabData")), 
           tabPanel("Tab 2", "This is tab number 2", uiOutput("tabPlot")) 
          ) 
          ) 
)) 
    , 
    server=shinyServer(function(input, output) { 

    create_data <- reactive({ 
     x<-seq(-2,2,length.out=100) 
     y1<-dnorm(x) 
     y2<-dunif(x) 
     y3<-dexp(x,2) 
     y4<-dbeta(x,1,2) 
     data<-data.frame(x,y1,y2,y3,y4) 
     names(data)<-c("x",paste(input$prefix,1:4,sep="")) 
     data 
    }) 

    output$tabData<-renderTable({ 
     data<-create_data() 
     data 
    }) 

    output$tabPlot = renderUI({ 
     data <- create_data() 
     tabnames<-names(data)[-1] 
     do.call(tabsetPanel, 
       lapply(tabnames,function(s){ 
       call("tabPanel",s,call('plotlyOutput',outputId=paste0("tabPlot_",s))) 
       }) 
    ) 
    }) 

    observe({ 
     data <- create_data() 
     tabnames<-names(data)[-1] 
     lapply(tabnames, function(s){output[[paste0("tabPlot_",as.character(s))]] <- renderPlotly({ 
     data <- create_data() 
     if (as.character(s) %in% names(data)){ 
      data.plot<-data[c("x",as.character(s))] 
      p <- plotthis(data.plot) 
      z <- ggplotly(p)   
     }else{ 
      z<-NULL 
     } 
     z 
     })}) 
    }) 

    plotthis<-function(data){ 
     names(data)<-c("x","y") 
     p<-ggplot(data=data,aes(x=x,y=y))+ 
     geom_line() 
     p 
    } 

    }) 
) 
+0

它與obsere if/else循環中的NULL有關,儘管這並不能解釋它返回到前一個數據集的事實。我不知道爲什麼你需要if/else循環,這是爲什麼沒有選擇前綴? – timfaber

+0

如果我刪除了if/else,那麼錯誤是該列在數據集中找不到。這就像它記得a1的舊選項卡選擇,並試圖應用於新的數據集(它有b1,b2,...),但沒有找到它。 –

+0

警告:[.data.frame中的錯誤:未定義列被選中 堆棧跟蹤(最裏面的第一個): 84:[.data。幀 83:[[#49] 82:ggplotly [#49] 81:FUNC 80:origRenderFunc 79:輸出$ tabPlot_a1 4: 3:do.call 2:print.shiny.appobj 1:

回答

2

這似乎是舊的輸出節點之一(與以前的名字)仍然被激活,你在建警衛但它似乎像他們甚至沒有幫助應該。我嘗試了幾種方法來修復它,比如修復輸出節點的名稱以不改變,或者更改爲從數字上選擇data的列,但最終更簡單的修復它 - 隔離create_data()語句之一。這抑制了不需要的輸出節點激活。

下面是該代碼observe - 當我添加isolate時,我得不到ggplotly NULL警告。請注意,只有一條線路需要更換時:

observe({ 
    data <- create_data() 
    tabnames<-names(data)[-1] 
    lapply(tabnames,function(s){output[[paste0("tabPlot_",as.character(s))]]<-renderPlotly({ 
    data <- isolate(create_data()) 
    if (as.character(s) %in% names(data)){ 
     data.plot<-data[c("x",as.character(s))] 
     p <- plotthis(data.plot) 
     z <- ggplotly(p)   
    }else{ 
     z<-NULL 
    } 
    z 
    }) 
}) 

順便說一句,我學到了很多與這個職位,我根本不知道observe可能會產生這樣的輸出節點。但是我想知道,如果你是這樣聰明地重命名數據列和輸出節點的話。你爲什麼想這麼做?

+1

拳頭,感謝您的意見。這僅僅是一個例子,原來閃亮的應用程序它實際上做的是讀取輸入文件,讀取列,然後單獨繪製每個列,如示例中所示(因此它不是「create_data」,是「read_data」)。它不是一個重命名的問題,它是有不同的數據集,不同的列。 –

+0

這樣做有什麼幫助嗎?我做了很多工作 –

+0

另外,昨天我發現完全刪除create_data()解決這個問題,試一試,似乎沒有更多的警告或錯誤,但它並沒有太大意義,實際上,爲了瞭解列名,renderPlotly應該再次使用create_data讀取數據集,因爲當你在選項卡上點擊而不是在改變數據集列時,圖形就會隨時生成,但看起來像lapply能夠使用在觀察開始時創建的變量數據並使用它。 –