conditionalPanel в создании нескольких динамических c вкладок - PullRequest
0 голосов
/ 18 июня 2020

Я разрабатываю блестящее приложение, в котором пользователь сможет описать заполненность комнат в нескольких домах. Основная идея кода - ввести количество домов (inputId = 'n_houses'), т.е. количество вкладок в mainPanel равно количеству введенных домов. Каждая вкладка дома должна быть связана с отдельным sidebarPanel, т.е. при доступе к вкладке дома в mainPanel отображается соответствующий sidebarPanel. В поле sidebarPanel указывается количество комнат (inputId = 'n_rooms') соответствующей вкладки дома. Наконец, каждой комнате присваивается значение заполняемости (inputId = 'occup'), которое может быть либо «liv» (гостиная), либо «dorm» (общежитие). Каждая вкладка mainPanel должна отображать заполняемость всех соответствующих комнат.

Ниже приведен простой пример входов :

  1. n_houses = 2 (два дома)
  2. n_rooms1 = 2 (две комнаты в первом доме) - 2.a. occ11 = 'liv' (гостиная); 2.b. occ12 = 'общежитие' (общежитие)
  3. n_rooms2 = 3 (три комнаты во втором доме) - 3.a. occ21 = 'общежитие' (общежитие); 3.b. busy22 = 'liv' (гостиная); 3. c. Occup23 = 'общежитие' (общежитие) Ps .: всего 5 заполненных комнат.

Тогда выходы должны быть:

  • вкладка 1 mainPanel (дом 1): «Результаты для дома 1: общежитие живого» * ​​1045 *
  • вкладка 2 основной панели (дом 2): «Результаты для дома 2: общежитие живого» * ​​1047 *

В фрагменте кода ниже показаны мои последние попытки решить эту проблему.


# shiny user interface
ui = shinyUI(
  fluidPage(
    headerPanel(
      h1('ROOMS OCCUPANCY', align = 'center')
    ),
    sidebarPanel(
      sliderInput(
        inputId = 'n_rooms',
        label = 'Choose the number of rooms in the correspondet house:',
        min = 2, max = 5, step = 1, value = 3
      ),
      uiOutput('rooms')
    ),
    mainPanel(
      sliderInput(
        inputId = 'n_houses', 
        label = 'Choose the number of houses:',
        min = 1, max = 20, step = 1, value = 1
      ),
      uiOutput('houses')
    )
  )
)

# auxiliar functions to shiny server
# generate room tab panel
GenRoomTab = function(ind_room, ind_house) {
  panel = tabPanel(
    title = paste('Room', ind_room),
    value = paste0(ind_house, ind_room),
    radioButtons(
      inputId = paste0('occup', ind_house, ind_room),
      label = 'Room occupancy:',
      choices = list('Living room' = paste0('liv', ind_house, ind_room),
                     'Dormitory' = paste0('dorm', ind_house, ind_room)),
      selected = paste0('liv', ind_house, ind_room)
    )
  )
  return(panel)
}
# generate room tabset panel
GenRoomTabset = function(ind_house, n_rooms) {
  tab_panels = lapply(1:n_rooms, GenRoomTab, ind_house)
  tabset_panel = do.call(tabsetPanel, tab_panels)
  condition_panel = list(condition = paste('input.tabselected ==', ind_house), tabset_panel)
  return(condition_panel)
}
# generate house tab panel
GenHouseTab = function(ind_house) {
  panel = tabPanel(
    title = paste('House', ind_house),
    value = ind_house,
    h4(paste('Results for house', ind_house, ':'))
  )
  return(panel)
}
# generate summary tab panel
GenSummTab = function() {
  panel = tabPanel(
    title = 'Summary'
  )
  return(list(panel))
}

# shiny server
server = shinyServer(
  function(input, output) {
    # define room tabset panels
    output$rooms = renderUI({
      room_tabsets = do.call(GenRoomTabset, list(1:input$n_houses, input$n_rooms))
      do.call(conditionalPanel, room_tabsets)
    })
    # define house tab panels
    output$houses = renderUI({
      house_tab_panels = lapply(1:input$n_houses, GenHouseTab)
      summ_tab_panel = GenSummTab()
      tab_panels = c(list(type = 'tab', id = 'tabselected'),
                     house_tab_panels, summ_tab_panel)
      do.call(tabsetPanel, tab_panels)
    })
  }
)

# associate ui to server

shinyApp (ui = ui, server = server)

Когда я запустите этот код, появится следующее предупреждающее сообщение:

Предупреждение: ошибка в radioButtons: аргумент 'selected' должен иметь длину 1105: stop 104: radioButtons 100: FUN [/ home / rodox / git / giz / app / app.r # 29] 99: lapply 98: [/home/rodox/git/giz/app/app.r#44] 96: renderUI [/ home / rodox / git / giz / app / app.r # 71] 95: func 82: origRenderFunc 81: output $ rooms 1: runApp

Я думаю, это связано с selected = paste0('liv', ind_house, ind_room), внутренней функцией GenRoomTab(). GenRoomTab() применяется внутри lapply(1:n_rooms, GenRoomTab, ind_house) внутри функции GenRoomTabset(). Однако мне это кажется странным, поскольку ind_house является вектором так же, как ind_room.

Еще одна сложность, с которой я столкнулся, - это отображение занятости всех комнат в соответствующей вкладке дома.

Я пытался решить это какое-то время, но не смог решить ... Надеюсь, кто-нибудь сможет меня спасти!

...