Измените selectInput на dateInput в Shiny

avatar
Antonio
9 августа 2021 в 03:20
244
2
1

Я создал приложение, которое срабатывает, когда я использую базу данных с помощью fileInput. База данных — это df, которую я вставил ниже, но она в формате Excel. Эту базу что есть в excel вставляю в fileInput.

df <- structure(
   list(date = c("2021-01-01","2021-01-02","2021-01-03","2021-01-04","2021-01-05"),
         d1 = c(0,1,4,5,6), d2 = c(2,4,5,6,7)),class = "data.frame", row.names = c(NA, -5L))
}  

Тем не менее, хотел бы я изменить selectInput(), который ссылается на даты, на dateInput()? Кроме того, я хотел бы, чтобы даты были представлены в стиле день-месяц-год.

library(shiny)
library(shinythemes)
library(openxlsx)
library(shinyBS)
library(shinyWidgets)
library(openxlsx)
library(writexl)
library(readxl)


ui <- fluidPage(
  
  ui <- shiny::navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
                          br(),
                          
                          tabPanel("",
                                   fileInput("file", "Please upload a file", accept = c(".xlsx")),
                                   sidebarLayout(
                                     sidebarPanel(
                                       
                                       selectInput("date", label = h4("Date"),""),
                                       selectInput("d1", label = h4("D1"),""),
                                       selectInput("d2", label = h4("D2"),""),
                                       br(),
                                       
                                     ),
                                     
                                     mainPanel( 
                                     ))
                          )))


server <- function(input, output, session) {
  df1 <- reactiveValues(dat=NULL)
  
  data <- eventReactive(input$file, {
    if (is.null(input$file)) return(NULL)
    df <- read_excel(input$file$datapath)
    df
  })
  
  observe({
    df1$dat <- data()
  })
  
  observeEvent(input$file, {
    
    if (!is.null(df1$dat)) {
      data <- df1$dat
      updateSelectInput(session, "date", label = "Date", unique(data$Date))
      updateSelectInput(session, "d1", label = "D1", unique(data$D1))
      updateSelectInput(session, "d2", label = "D2", unique(data$D2))
    }
    
  })
  
}

shinyApp(ui = ui, server = server)
Источник

Ответы (2)

avatar
Sam Rogers
9 августа 2021 в 05:15
1

Исходя из вашего другого вопроса, это довольно просто, если ваш входной файл последовательно назван и организован (хотя это не следует предполагать, и вам было бы разумно проверить это при вводе набора данных - сделать это в операторе else данных eventReactive()).

Предполагая, что вы также хотите, чтобы были доступны только значения, которые присутствуют в вашем наборе данных, вот полный код, отредактированный из моего ответа на ваш другой вопрос, который должен позволить вам использовать тип ввода dateInput() с произвольными датами из входной файл.

Еще одно замечание: поскольку компонент пользовательского интерфейса создается на сервере после загрузки данных, поля выбора даты обычно не будет, поскольку оно еще не создано. Поэтому я добавил фиктивное поле выбора даты, которое будет обновляться, когда кто-то загружает файл. В основном это сделано для согласованности пользовательского интерфейса, чтобы он не появлялся внезапно, когда кто-то загружает файл, и в противном случае его не было.

library(shiny)
library(shinythemes)
library(openxlsx)
library(shinyBS)
library(shinyWidgets)
library(openxlsx)
library(writexl)
library(readxl)
library(DT)

ui <- fluidPage(
    
    ui <- shiny::navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
                            br(),
                            
                            tabPanel("",
                                     fileInput("file", "Please upload a file", accept = c(".xlsx")),
                                     sidebarLayout(
                                         sidebarPanel(
                                             
                                             uiOutput("date"),
                                             selectInput("d1", label = h4("D1"),""),
                                             selectInput("d2", label = h4("D2"),""),
                                             br(),
                                             
                                         ),
                                         
                                         mainPanel( 
                                         ))
                            )))


server <- function(input, output, session) {
    data <- eventReactive(input$file, {
        if (is.null(input$file)) {
            return(NULL)
        }
        else {
            df <- read_excel(input$file$datapath)
            return(df)
        }
    })
    
    output$date <- renderUI({
        if (!is.null(input$file)) {
            
            all_dates <- seq(as.Date(min(data()$date)), as.Date(max(data()$date)), by = "day")
            disabled <- as.Date(setdiff(all_dates, as.Date(data()$date)), origin = "1970-01-01")
            
            dateInput(input = "date", 
                      label = "Select Date",
                      min = min(data()$date),
                      max = max(data()$date),
                      value = max(data()$date),
                      format = "dd-mm-yyyy",
                      datesdisabled = disabled)
        }
        else {
            dateInput(input = "date", 
                      label = "Select Date",
                      min = min("1970-01-01"),
                      max = max(Sys.Date()),
                      format = "dd-mm-yyyy")
        }
    })
    
    observeEvent(input$file, {
        
        req(data)
        data <- data()
        data$date <- as.Date(data$date)
        print(data)
        updateSelectInput(session, "d1", label = "D1", unique(data$d1))
        updateSelectInput(session, "d2", label = "D2", unique(data$d2))
    })
}

shinyApp(ui = ui, server = server)
Antonio
9 августа 2021 в 14:29
0

Еще раз спасибо Сэм! :)

Sam Rogers
9 августа 2021 в 22:50
0

Не за что, рад, что смог помочь :)

avatar
Ronak Shah
9 августа 2021 в 03:35
2

Вы можете изменить код selectInput для даты на dateInput

dateInput("date", label = h4("Date"),"", format = 'dd-mm-yyyy'),

и в observeEvent заменить updateSelectInput на updateDateInput

updateDateInput(session, "date", label = "Date", min = min(data$date), max = max(data$date))

Обратите внимание, что data$date должен относиться к классу Date, для этого запустите data$date <- as.Date(data$date).


Для тестирования я записал общие данные в файл Excel с именем file.xlsx, используя writexl::write_xlsx(df, 'file.xlsx').

Полный код приложения -

library(readxl)
library(shiny)

ui <- fluidPage(
  
  ui <- shiny::navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
                          br(),
                          
                          tabPanel("",
                                   fileInput("file", "Please upload a file", accept = c(".xlsx")),
                                   sidebarLayout(
                                     sidebarPanel(
                                       
                                       dateInput("date", label = h4("Date"),"", format = 'dd-mm-yyyy'),
                                       selectInput("d1", label = h4("D1"),""),
                                       selectInput("d2", label = h4("D2"),""),
                                       br(),
                                       
                                     ),
                                     
                                     mainPanel( 
                                     ))
                          )))


server <- function(input, output, session) {
  
  data1 <- eventReactive(input$file, {
    if (is.null(input$file)) return(NULL)
    df <- read_excel(input$file$datapath)
    df
  })

  
  observeEvent(input$file, {
    
      req(data1)
      data <- data1()
      data$date <- as.Date(data$date)
      updateDateInput(session, "date", label = "Date", min = min(data$date), max = max(data$date))
      updateSelectInput(session, "d1", label = "D1", unique(data$d1))
      updateSelectInput(session, "d2", label = "D2", unique(data$d2))
    
  })
  
}

shinyApp(ui = ui, server = server)
Antonio
9 августа 2021 в 04:14
0

Спасибо за ответ! Я внес коррективы, как было предложено. Но я не совсем понял эту часть data$date <- as.Date(data$date) Где я могу сделать эту настройку? Не могли бы вы показать в коде? Еще раз спасибо!

Ronak Shah
9 августа 2021 в 04:20
0

По сути, столбец даты должен относиться к классу Date. Вы можете включить его после data <- df1$dat и перед updateDateInput в observeEvent.

Ronak Shah
9 августа 2021 в 04:48
0

@ Хосе, я включил полный код приложения.

Antonio
9 августа 2021 в 14:28
0

Спасибо Ронак за предложение, которое вы предоставили, но оно все еще не очень хорошо сработало для моего случая, в любом случае я очень ценю вашу помощь! :)