Эффективная фильтрация кадра данных в R блестящий по значениям в нескольких столбцах - PullRequest
0 голосов
/ 16 ноября 2018

Я хотел бы знать эффективный способ сделать следующее. Имея реактив dataframe() в блестящем приложении. Я хочу иметь два реактивных входа (каждый с 2 ​​возможностями TRUE или FALSE), которые поднастроят строки на основе значения в двух столбцах соответственно. Если у меня есть только один вход (и один столбец photos), я делаю что-то вроде:

df<-reactive({
  df<-mydf
  if(input$myinput==FALSE)
  {
    df<-df[!df$photos=="",]
  }
  else{
    df
  }
}) 

Проблема в том, что если у меня есть два (или более) входа (и столбца), код будет слишком сильно увеличиваться, если я буду использовать вложенные if и else внутри if и else выше в примере, чтобы учесть 4 возможности двух TRUE/FALSE входов.

РЕДАКТИРОВАТЬ: Воспроизводимый, сделать второй ввод работать без слишком много if и else:

server <- function(input, output, session) { 
  df<-reactive({
    df<-iris
    if(input$Petalw==T)
    {
      df<-df[df$Petal.Width==0.2,]
    }
    else{
      df
    }
  }) 
  output$table <- DT::renderDataTable(
    DT::datatable(df(), options = list(searching = FALSE,pageLength = 25))
  )
}
ui <- navbarPage(
  title = 'Select values in two columns based on two inputs respectively',
  fluidRow(
    column(width = 3,
           checkboxInput("Petalw","PetalWithIs0.2",T),
           checkboxInput("PetalL","PetalLengthis1.4",T)
    ),
    column(9,
  tabPanel('Table',       DT::dataTableOutput('table'))
  )
  )
)
shinyApp(ui, server) 

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Вы можете позволить пользователю выбрать значение для одного столбца, установить поднабор ваших данных на основе этого значения, а затем использовать renderUI и генерировать динамические раскрывающиеся списки selectInput со значениями из других столбцов.

server <- function(input, output, session) { 
  df <- reactive({
    subset(iris, Petal.Width == input$Petalw)
  })

  # Extract list of Petal Lengths from selected data - to be used as a filter
  p.lengths <- reactive({
    unique(df()$Petal.Length)
  })

  # Filter based on Petal Length
  output$PetalL <- renderUI({
    selectInput("PetalLengthSelector", "PetalLength", as.list(p.lengths()))
  })

  # Subset this data based on the values selected by user
  df_1 <- reactive({
    foo <- subset(df(), Petal.Length == input$PetalLengthSelector)
    return(foo)
  })

  output$table <- DT::renderDataTable(
    DT::datatable(df_1(), options = list(searching = FALSE,pageLength = 25))
  )
}
ui <- navbarPage(
  title = 'Select values in two columns based on two inputs respectively',
  fluidRow(
    column(width = 3,
           selectInput("Petalw","PetalWidth", choices = unique(iris$Petal.Width)),
           uiOutput("PetalL")
    ),
    column(9,
           tabPanel('Table', DT::dataTableOutput('table'))
    )
  )
)
shinyApp(ui, server)
0 голосов
/ 16 ноября 2018

Вы можете получить доступ к входам через input[[inputName]], где inputName - это имя вашего входа (например, «Sepal.Length-7.9»).Затем вы можете проверить все входы через

if(input[[inputName]]){
   split <- strsplit(inputName, "-")[[1]]
   name <- split[1]
   treshold <- as.numeric(split[2])
   global$filter[, inputName ==colnames(filter)] <- iris[name] == treshold
}else{
   global$filter[, inputName ==colnames(filter)] = TRUE
}

Входы, которые вы можете создать с помощью renderUI():

output$checkBoxes <- renderUI({
    lapply(inputNames, function(inputName) checkboxInput(inputName, inputName, FALSE))
  })

В примере я использую максимум всех числовых столбцов.

Полный код будет выглядеть так:

restr <- apply(iris, 2, max)[1:4]
inputNames <- paste(names(restr), restr, sep = "-") 
filter = sapply(inputNames, function(inputName) c(inputName = return(rep(TRUE, dim(iris)[1]))))


server <- function(input, output, session) { 
  global <- reactiveValues(filter = filter)

  df <- reactive({
      for(inputName in inputNames){
        if(!is.null(input[[inputName]])){
          isolate({
            if(input[[inputName]]){
              split <- strsplit(inputName, "-")[[1]]
              name <- split[1]
              treshold <- as.numeric(split[2])
              global$filter[, inputName ==colnames(filter)] <- iris[name] == treshold
            }else{
              global$filter[, inputName ==colnames(filter)] = TRUE
            }
          })
        }
      }
      iris[rowSums(global$filter) == 4, ]
    })


  output$checkBoxes <- renderUI({
    lapply(inputNames, function(inputName) checkboxInput(inputName, inputName, FALSE))
  })

  output$table <- DT::renderDataTable(
    DT::datatable(df(), options = list(searching = FALSE,pageLength = 25))
  )
}
ui <- navbarPage(
  title = 'Select values in two columns based on two inputs respectively',
  fluidRow(
    column(width = 3,
           uiOutput("checkBoxes")
    ),
    column(9,
           tabPanel('Table', DT::dataTableOutput('table'))
    )
  )
)
shinyApp(ui, server) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...