简体   繁体   English

Ggplot2 在闪亮的应用程序中显示错误消息

[英]Ggplot2 displaying error message in shiny app

Please I am trying to convert the graphs in my shiny app into ggplot2 graphs.请我尝试将我闪亮的应用程序中的图形转换为 ggplot2 图形。 I use a reactive function to generate the values of financial ratios, which are plotted in bar graphs and pie charts, eg Profit/Turnover.我使用反应函数来生成财务比率的值,这些值绘制在条形图和饼图中,例如利润/营业额。 When you load the app, by default, each input field (profit input fields and turnover input fields) contains values, whose ratios are plotted in the graphs.当您加载应用程序时,默认情况下,每个输入字段(利润输入字段和营业额输入字段)都包含值,其比率绘制在图表中。 The ggplot2 graph displays when the app is loaded. ggplot2 图在应用加载时显示。 But, when I clear an input field, say in profit, so that I can enter a new value, I get the following error message in my console:但是,当我清除输入字段时,比如利润,以便我可以输入一个新值,我在控制台中收到以下错误消息:

Warning in profit/turnover :

  longer object length is not a multiple of shorter object length

Warning: Error in data.frame: arguments imply differing number of rows: 5, 4

  131: stop

  130: data.frame

  129: <reactive:profitability.df> [C:\Users\Idiaye\Documents\R data\mavisanalytic/app.R#446]

  113: profitability.df

   99: renderPlotly [C:\Users\Idiaye\Documents\R data\mavisanalytic/app.R#451]

   98: func

   95: func

   82: origRenderFunc

   81: output$bar

    1: shiny::runApp

The app is designed to compute and plot financial ratios over just five years;该应用程序旨在计算和绘制五年内的财务比率; hence five data input fields each for profit and turnover.因此有五个数据输入字段,每个字段用于利润和营业额。 Nevertheless, I want a user to be able to analyse financial performance over any number of years they choose.尽管如此,我希望用户能够分析他们选择的任何年份的财务业绩。 But, when an input field is cleared, I get the above error message.但是,当清除输入字段时,我收到上述错误消息。 I didn't experience this problem prior to converting my plots to ggplot2.在将我的绘图转换为 ggplot2 之前,我没有遇到过这个问题。 Below is my reproducible code:以下是我的可重现代码:

library(shiny)
library(ggplot2)
library(plotly)

ui<-navbarPage(
    windowTitle="Reprex",fluid=TRUE, title=strong("Reprex"),
    tabPanel(title="Reprex App",
        sidebarLayout(
            sidebarPanel(width=2,
                actionButton("delete",strong("Clear Fields"),icon=icon("broom")),br(),br(),  
                textInput("pro","Profit 1",value="100000",width=150),
                textInput("prof","Profit 2",value="150000",width=150),
                textInput("profs","Profit 3",value="200000",width=150),
                textInput("profit","Profit 4",value="250000",width=150),
                textInput("profits","Profit 5",value="300000",width=150),
                hr(),
                h4(strong("Turnover figures:")),
                actionButton("remove",strong("Clear Fields"),icon=icon("broom")),br(),br(),
                textInput("turn","Turnover 1",value="350000",width=150),
                textInput("turno","Turnover 2",value="300000",width=150),
                textInput("turnov","Turnover 3",value="420000",width=150),
                textInput("turnover","Turnover 4",value="600000",width=150),
                textInput("turnovers","Turnover 5",value="550000",width=150),
                actionButton("go",strong("Calculate Ratio"),icon=icon("caret-right"))
                
            ),mainPanel(
                plotlyOutput("plot")
            )
        )
    )
)

server<-function(input,output,session){
    
    observeEvent(input$delete,{
        
        updateTextInput(session,"pro",value="",placeholder="0")
        updateTextInput(session,"prof",value="",placeholder="0")
        updateTextInput(session,"profs",value="",placeholder="0")
        updateTextInput(session,"profit",value="",placeholder="0")
        updateTextInput(session,"profits",value="",placeholder="0")
    })
    
    
    observeEvent(input$remove,{
        
        updateTextInput(session,"turn",value="",placeholder="0")
        updateTextInput(session,"turno",value="",placeholder="0")
        updateTextInput(session,"turnov",value="",placeholder="0")
        updateTextInput(session,"turnover",value="",placeholder="0")
        updateTextInput(session,"turnovers",value="",placeholder="0")
    })
    
    profits<-reactive({
        as.numeric(c(
            if(input$pro>0){input$pro},
            if(input$prof>0){input$prof},
            if(input$profs>0){input$profs},
            if(input$profit>0){input$profit},
            if(input$profits>0){input$profits}
        ))
    })
    
    turnover<-reactive({
        as.numeric(c(
            if(input$turn>0){input$turn},
            if(input$turno>0){input$turno},
            if(input$turnov>0){input$turnov},
            if(input$turnover>0){input$turnover},
            if(input$turnovers>0){input$turnovers}
        ))
    })
    
    year<-reactive({
        c(
            if(input$pro>0){"Year 1"},
            if(input$prof>0){"Year 2"},
            if(input$profs>0){"Year 3"},
            if(input$profit>0){"Year 4"},
            if(input$profits>0){"Year 5"}
        )
    })
    profit.ratio<-function(profits,turnover){
        profitability<-round(profits/turnover*100,1)
        return(profitability)
    }
  profitability<-reactive({profit.ratio(profits(),turnover())}) 
  
  
  
  profit.df<-reactive({data.frame(profitability(),year())})
  
  output$plot<-renderPlotly({
      input$go
      isolate(profit.df()%>%
          ggplot()+aes(x=year(),y=profitability(),fill=year())+geom_bar(stat="identity")+
          labs(x="Years",y="Profitability ratios (%)",fill="Years")+scale_fill_brewer(palette="Set1")+
              geom_text(label=profitability(),position=position_stack(vjust=0.8)))
  })
}
shinyApp(ui=ui,server=server)

Thanks in anticipation of your suggestions.感谢您的建议。

You can use req to make sure that all input fulfill the conditions needed for further processing.您可以使用req来确保所有input满足进一步处理所需的条件。
This will avoid the warning message in the console.这将避免控制台中的警告消息。

Try:尝试:

 profits<-reactive({
    req(input$pro>0,
        input$prof>0,
        input$profs>0,
        input$profit>0,
        input$profits>0)
    
    as.numeric(c(input$pro,
                 input$prof,
                 input$profs,
                 input$profit,
                 input$profits
    ))
})

Another option is to use validate in order to display an useful information message as long as the conditions aren't met:另一种选择是使用validate以便在不满足条件时显示有用的信息消息:

  profits<-reactive({
    validate(need(input$pro>0 &
                  input$prof>0 &
                  input$profs>0 &
                  input$profit>0 &
                  input$profits>0,'Please fill all coefs'))
    
    as.numeric(c(input$pro,
                 input$prof,
                 input$profs,
                 input$profit,
                 input$profits
    ))
  })

在此处输入图片说明

You were not handling the missing values when you cleared the profits or turnover.您在清算利润或营业额时没有处理缺失值。 I created a new reactive dataframe where it is easier to check if all fields are missing for profit or turnover.我创建了一个新的反应式数据框,可以更轻松地检查所有字段是否因利润或营业额而丢失。 Try this code.试试这个代码。

ui<-navbarPage(
  windowTitle="Reprex",fluid=TRUE, title=strong("Reprex"),
  tabPanel(title="Reprex App",
           sidebarLayout(
             sidebarPanel(width=2,
                          actionButton("delete",strong("Clear Fields"),icon=icon("broom")),br(),br(),  
                          textInput("pro","Profit 1",value="100000",width=150),
                          textInput("prof","Profit 2",value="150000",width=150),
                          textInput("profs","Profit 3",value="200000",width=150),
                          textInput("profit","Profit 4",value="250000",width=150),
                          textInput("profits","Profit 5",value="300000",width=150),
                          hr(),
                          h4(strong("Turnover figures:")),
                          actionButton("remove",strong("Clear Fields"),icon=icon("broom")),br(),br(),
                          textInput("turn","Turnover 1",value="350000",width=150),
                          textInput("turno","Turnover 2",value="300000",width=150),
                          textInput("turnov","Turnover 3",value="420000",width=150),
                          textInput("turnover","Turnover 4",value="600000",width=150),
                          textInput("turnovers","Turnover 5",value="550000",width=150),
                          actionButton("go",strong("Calculate Ratio"),icon=icon("caret-right"))
                          
             ),mainPanel(
               plotlyOutput("plot")
             )
           )
  )
)

server<-function(input,output,session){
  
  DF1 <- reactiveValues(data=NULL)
  
  observeEvent(input$delete,{
    
    updateTextInput(session,"pro",value="",placeholder="0")
    updateTextInput(session,"prof",value="",placeholder="0")
    updateTextInput(session,"profs",value="",placeholder="0")
    updateTextInput(session,"profit",value="",placeholder="0")
    updateTextInput(session,"profits",value="",placeholder="0")
  })
  
  observeEvent(input$remove,{
    
    updateTextInput(session,"turn",value="",placeholder="0")
    updateTextInput(session,"turno",value="",placeholder="0")
    updateTextInput(session,"turnov",value="",placeholder="0")
    updateTextInput(session,"turnover",value="",placeholder="0")
    updateTextInput(session,"turnovers",value="",placeholder="0")
  })

  
  findata <- reactive({
    years <- c("Year 1", "Year 2", "Year 3", "Year 4", "Year 5")
    profits <- c(input$pro, input$prof, input$profs, input$profit, input$profits)
    turnovers <- c(input$turn,input$turno,input$turnov,input$turnover,input$turnovers)
    fdata <- data.frame(profitability=c(),year=c())
    chkp <- sum(is.na(as.numeric(profits)))
    chkt <- sum(is.na(as.numeric(turnovers)))
    if (chkp==5 | chkt==5) {
      fdata <- NULL
    }else{
      lapply(1:5, function(i){
        if (!is.null(profits[i]) & !is.null(turnovers[i]) ) {
          if (profits[i]>0 & turnovers[i]>0) {
            pfy <- round(as.numeric(profits[i])/as.numeric(turnovers[i])*100,1)
            fdata <<- rbind(fdata,data.frame(profitability=pfy,year=years[i]))
          }
          
        }
        
      })
    }
    
    fdata
  })
  
  observe({DF1$data <- findata()})
  
  #observeEvent(input$go, {
    output$plot<-renderPlotly({
      input$go
     
      df <- DF1$data
      
      chkpfy <- sum(is.na(as.numeric(df$profitability)))
      if (is.null(df)) return(NULL)
      if (chkpfy==5) { 
        return(NULL)
      }else{
        p <-  ggplot(data=df, aes(x=year, y=profitability, fill=year )) +
          geom_bar(stat="identity") +
          labs(x="Years",y="Profitability ratios (%)",fill="Years") +
          scale_fill_brewer(palette="Set1") +
          geom_text(label=df$profitability, position=position_stack(vjust=0.8))
                        
        ggplotly(p)
      }
      
    })
  #})

}
shinyApp(ui=ui,server=server)

output输出

在此处输入图片说明

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

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