0

我一直在网上搜索我的问题的答案,我看过这里:

https://shiny.rstudio.com/articles/dynamic-ui.html

https://shiny.rstudio.com/articles/req.html

filter_impl(.data, quo) 中的错误:结果的长度必须为 259,而不是 399

闪亮的 renderUI selectInput 返回 NULL

闪亮的动态 UI:无法打印使用 renderUI 创建的 uiOutput 的结果

如何在ui.R中获取uioutput中的值并将其发送回server.R?

https://community.rstudio.com/t/dynamic-ui-cant-print-results-from-uioutput-created-with-renderui/6937

这些都没有帮助。

设置:

我有一组不同行业的数据集和这些行业的财务比率。比率的选择取决于行业的选择。此外,变量的选择取决于行业中公司的规模。例如,我可能只想看看 Industry1 中资产低于 50 亿美元的公司,以及该行业中该规模公司的相关比率。因此,动态UI来自选择和行业,然后根据行业选择我要调查的尺寸等级。并非所有行业都将按大小进行相同的细分,有些行业有 2 个规模排名,有些可能有 4 或 5 个。最后,这些比率衡量公司财务的各个方面,如债务、收入、效率等,因此我应该四列对于具有一组比率的每个维度,每个维度旁边都有一个复选框。

问题:

我必须按行业过滤我的 data.frame 的函数返回一列大小等级,以在 renderUI 中进行选择。但是,在以下三个步骤之间的某个位置,输出变为 NULL。因此,我无法按行业和大小过滤我想选择的比率,并且闪亮会返回一个带有标题和下拉菜单但没有可供选择的变量的页面。

步骤1。

    output$secondSelection = renderUI({
    size_filter_choice = dummyData %>% filter(Industry == input$industry) %>% distinct(Size)
    print("Step 1.")
    print(size_filter_choice)
    selectInput(inputId = "size",label="Sizes",choices = as.list(size_filter_choice[,"Size"]),selectize=FALSE) 
  })

第2步。

uiOutput("secondSelection")

步骤 3。

main_ratio_set <- reactive({

    print("Step 3")
    print(input$size)
    print(input$industry)
    req(input$size)

    user_filter <- dummyData %>% filter(Industry == input$industry & Size == input$size)

    return(user_filter)

  })

  outputOptions(output,"secondSelection",suspendWhenHidden = FALSE)

打印函数返回以下内容:

收听http://127.0.0.1:5301

[

1] "Step 1."
   Size
1 Size1
2 Size2
[1] "Step 3"
NULL
[1] "Industry1"

下面是带有虚拟数据集的代码,它与我在使用这些专有数据时遇到的问题非常接近。我正在运行 RStudio 版本 0.98.1103,R 版本为 3.4.1。预先感谢您的帮助。

library(plyr)
library(dplyr)
library(shiny)
library(shinydashboard)

dummyData <- data.frame(matrix(nrow=0,ncol=4,dimnames=list(c(),c("Ratio","Dimensions","Industry","Size"))))

industry_n <- 5
dims <- 4

for(i in 1:industry_n){
  s = sample(1:5,1)
  for(sz in 1:s){
    for(d in 1:dims){
      ratios <- sample(1:10,1)
      df <- data.frame(Ratio = paste0("Ratio",ratios))
      df <- df %>% mutate(Dimensions = paste0("Dimension",d),
                       Industry = paste0("Industry",i),
                       Size = paste0("Size",sz))
      dummyData <- rbind(dummyData,df)
    }
  }
}


ind_n <- paste0("Industry",1:industry_n)

runApp(list(
  ui = fluidPage(
    fluidRow(
      column(5,
             selectInput("industry",label="Industry",choices = ind_n,selected="Industry1"),
             uiOutput("secondSelection")
      ),
      fluidRow(
        column(width = wd,
               list(h3("Dimension 1"), 
                    tags$div(align = 'left', 
                             class = 'multicol', 
                             uiOutput("dim1")))),
        column(width = wd,
               list(h3("Dimension 2"), 
                    tags$div(align = 'left', 
                             class = 'multicol', 
                             uiOutput("dim2")))),
        column(width = wd,
               list(h3("Dimension 3"), 
                    tags$div(align = 'left', 
                             class = 'multicol', 
                             uiOutput("dim3")))),
        column(width = wd,
               list(h3("Dimension 4"), 
                    tags$div(align = 'left', 
                             class = 'multicol', 
                             uiOutput("dim4"))))
      )
      )),

server = function(input, output,session) {

  output$secondSelection = renderUI({
    size_filter_choice = dummyData %>% filter(Industry == input$industry) %>% distinct(Size)
    print("Step 1.")
    print(size_filter_choice)
    selectInput(inputId = "size",label="Sizes",choices = as.list(size_filter_choice[,"Size"]),selectize=FALSE) 
  })

  main_ratio_set <- reactive({

    print("Step 3")
    print(input$size)
    print(input$industry)
    req(input$size)

    user_filter <- dummyData %>% filter(Industry == input$industry & Size == input$size)

    return(user_filter)

  })

  outputOptions(output,"secondSelection",suspendWhenHidden = FALSE)

ratio_filter_dim1 = reactive({

  ratio_select <- main_ratio_set() %>% filter(Risk.Dimension == "Dimension1") %>% distinct(Ratio)
  ratio_select <- as.list(as.character(ratio_select[,"Ratio"]))
  return(ratio_select)
})


output$dim1 = renderUI({
  checkboxGroupInput(inputId = "dim1",label=NULL,choices = ratio_filter_dim1(),inline=F)
})

ratio_filter_dim2 = reactive({
    ratio_select <- main_ratio_set() %>% filter(Risk.Dimension == "Dimension2") %>% distinct(Ratio)
  ratio_select <- as.character(ratio_select[,"Ratio"])
  return(ratio_select)
})


output$dim2 = renderUI({
  checkboxGroupInput(inputId = "dim2",label=NULL,choices = ratio_filter_dim2(),inline=F)
})

ratio_filter_dim3 = reactive({
  ratio_select <- main_ratio_set() %>% filter(Risk.Dimension == "Dimension3") %>% distinct(Ratio)
  ratio_select <- as.character(ratio_select[,"Ratio"])
  return(ratio_select)
})


output$dim3 = renderUI({
  checkboxGroupInput(inputId = "dim3",label=NULL,choices = ratio_filter_dim3(),inline=F)
})

ratio_filter_dim4 = reactive({

  ratio_select <- main_ratio_set() %>% filter(Risk.Dimension == "Dimension4") %>% distinct(Ratio)
  ratio_select <- as.character(ratio_select[,"Ratio"])
  return(ratio_select)
})

output$dim4 = renderUI({
  checkboxGroupInput(inputId = "dim4",label=NULL,choices = ratio_filter_dim4(),inline=F)
})
}
))
4

1 回答 1

0

在启动服务器之前,构建一个查找表或查找列表并将其用于您的行业、规模和维度查找。我将行业大小查找放在server.R文件之外,因为它不需要是反应性的,而在文件ratio_filter_dim_x内部,server.R因为它确实需要是反应性的。

此外,作为一种礼仪,请尽量确保您的示例在在线发布时只抛出最少的错误,并且包含尽可能少的代码行来重现问题。

这是我的修复:

library(plyr)
library(dplyr)
library(shiny)
library(shinydashboard)

dummyData <- data.frame(matrix(nrow=0,ncol=4,dimnames=list(c(),c("Ratio","Dimensions","Industry","Size"))))

industry_n <- 5
dims <- 4

for(i in 1:industry_n){
  s = sample(1:5,1)
  for(sz in 1:s){
    for(d in 1:dims){
      ratios <- sample(1:10,1)
      df <- data.frame(Ratio = paste0("Ratio",ratios))
      df <- df %>% mutate(Dimensions = paste0("Dimension",d),
                          Industry = paste0("Industry",i),
                          Size = paste0("Size",sz))
      dummyData <- rbind(dummyData,df)
    }
  }
}

colnames(dummyData)[which(colnames(dummyData)=="Dimensions")]<- "Risk.Dimension"

ind_n <- paste0("Industry",1:industry_n)
wd=6

# Generating a non-reactive lookup list, could also be a dataframe if so desired

industry_size_lookup_list<- lapply(unique(dummyData$Industry), function(x){unique(dummyData[which(dummyData$Industry == x), "Size"])})
names(industry_size_lookup_list)<- unique(dummyData$Industry)

runApp(list(
  ui = fluidPage(
    fluidRow(
      column(5,
             selectInput("industry",label="Industry",choices = names(industry_size_lookup_list),selected=names(industry_size_lookup_list)[1]),
             uiOutput("secondSelection")
      ),
      fluidRow(
        column(width = wd,
               list(h3("Dimension 1"),
                    tags$div(align = 'left',
                             class = 'multicol',
                             uiOutput("dim1")))),
        column(width = wd,
               list(h3("Dimension 2"),
                    tags$div(align = 'left',
                             class = 'multicol',
                             uiOutput("dim2")))),
        column(width = wd,
               list(h3("Dimension 3"),
                    tags$div(align = 'left',
                             class = 'multicol',
                             uiOutput("dim3")))),
        column(width = wd,
               list(h3("Dimension 4"),
                    tags$div(align = 'left',
                             class = 'multicol',
                             uiOutput("dim4"))))
      )
    )),

  server = function(input, output,session) {

    output$secondSelection<- shiny::renderUI({
      if(!is.null(input$industry)){
        the_valid_choices<- industry_size_lookup_list[[which(names(industry_size_lookup_list)==input$industry)]]
      }
      if(is.null(input$industry)){
        the_valid_choices<- "Please Select An Industry"
      }
      selectInput(inputId = "size",label="Sizes",choices = the_valid_choices,selectize=FALSE, multiple = FALSE)
    })

    main_ratio_set<- shiny::reactive({
      if(!is.null(input$industry)){
        if(!is.null(input$size)){
          tmp<- dummyData[which(dummyData$Industry ==  input$industry & dummyData$Size == input$size),]
        }
      }
    })
    # The reactive lookup list
    ratio_filter_dim_x<- shiny::reactive({
      if(!is.null(main_ratio_set())){
        tmp<- lapply(unique(main_ratio_set()$Risk.Dimension), function(x){as.character(unique(main_ratio_set()[which(main_ratio_set()$Risk.Dimension == x), "Ratio"]))})
        names(tmp)<- unique(main_ratio_set()$Risk.Dimension)
        tmp
      }
    })

    observe({
      if(!is.null(ratio_filter_dim_x())){
        cat("STR of ratio_filter_dim_x", str(ratio_filter_dim_x()), "\n")
        cat("names of ratio_filter_dim_x", names(ratio_filter_dim_x()), "\n")
        }
      })

    # Use modules for the below. See link:
    # https://www.cultureofinsight.com/blog/2018/01/05/2017-11-13-reproducible-shiny-app-development-with-modules/

    output$dim1 = renderUI({
      if(!is.null(ratio_filter_dim_x())){
        shiny::checkboxGroupInput(inputId = "dim1",label=NULL,choices = ratio_filter_dim_x()[["Dimension1"]],inline=F)
      }
    })
    output$dim2 = renderUI({
      if(!is.null(ratio_filter_dim_x())){
        shiny::checkboxGroupInput(inputId = "dim2",label=NULL,choices = ratio_filter_dim_x()[["Dimension2"]],inline=F)
      }
    })
    output$dim3 = renderUI({
      if(!is.null(ratio_filter_dim_x())){
        shiny::checkboxGroupInput(inputId = "dim3",label=NULL,choices = ratio_filter_dim_x()[["Dimension3"]],inline=F)
      }
    })
    output$dim4 = renderUI({
      if(!is.null(ratio_filter_dim_x())){
        shiny::checkboxGroupInput(inputId = "dim4",label=NULL,choices = ratio_filter_dim_x()[["Dimension4"]],inline=F)
      }
    })


  }
))

希望这可以帮助。它仍然可以进一步简化和精简。

于 2019-03-21T20:57:40.517 回答