R Shiny文件上传校验与Reset按钮清空日历功能咨询
R Shiny 功能实现方案
修改说明
- 针对文件上传校验需求:在文件读取逻辑中增加两层校验,第一层校验文件后缀是否为xlsx,第二层校验读取后的数据是否包含所需的必填列,校验失败时弹出顶部短提示。
- 针对Reset清空需求:将数据存储对象改为可手动赋值的
reactiveVal,点击Reset时直接将数据重置为NULL,所有依赖数据生成的组件(日期选择框、分类下拉框、绘图)会自动隐藏,仅保留文件上传组件。
完整修改后代码
library(shiny) library(shinythemes) library(dplyr) library(tidyverse) library(lubridate) library(stringr) library(readxl) library(shinyjs) function.test<-function(){ df1 <- structure( list(date1= c("2021-06-28","2021-06-28","2021-06-28"), date2 = c("2021-07-01","2021-07-02","2021-07-04"), Category = c("ABC","ABC","ABC"), Week= c("Wednesday","Wednesday","Wednesday"), DR1 = c(4,1,0), DR01 = c(4,1,0), DR02= c(4,2,0),DR03= c(9,5,0), DR04 = c(5,4,0),DR05 = c(5,4,0),DR06 = c(5,4,0),DR07 = c(5,4,0),DR08 = c(5,4,0)), class = "data.frame", row.names = c(NA, -3L)) return(df1) } f1 <- function(df1, dmda, CategoryChosse) { x<-df1 %>% select(starts_with("DR0")) x<-cbind(df1, setNames(df1$DR1 - x, paste0(names(x), "_PV"))) PV<-select(x, date2,Week, Category, DR1, ends_with("PV")) med<-PV %>% group_by(Category,Week) %>% summarize(across(ends_with("PV"), median)) SPV<-df1%>% inner_join(med, by = c('Category', 'Week')) %>% mutate(across(matches("^DR0\\d+$"), ~.x + get(paste0(cur_column(), '_PV')), .names = '{col}_{col}_PV')) %>% select(date1:Category, DR01_DR01_PV:last_col()) SPV<-data.frame(SPV) mat1 <- df1 %>% filter(date2 == dmda, Category == CategoryChosse) %>% select(starts_with("DR0")) %>% pivot_longer(cols = everything()) %>% arrange(desc(row_number())) %>% mutate(cs = cumsum(value)) %>% filter(cs == 0) %>% pull(name) (dropnames <- paste0(mat1,"_",mat1, "_PV")) SPV <- SPV %>% filter(date2 == dmda, Category == CategoryChosse) %>% select(-any_of(dropnames)) if(length(grep("DR0", names(SPV))) == 0) { SPV[head(mat1,10)] <- NA_real_ } datas <-SPV %>% filter(date2 == ymd(dmda)) %>% group_by(Category) %>% summarize(across(starts_with("DR0"), sum)) %>% pivot_longer(cols= -Category, names_pattern = "DR0(.+)", values_to = "val") %>% mutate(name = readr::parse_number(name)) colnames(datas)[-1]<-c("Days","Numbers") datas <- datas %>% group_by(Category) %>% slice((as.Date(dmda) - min(as.Date(df1$date1) [ df1$Category == first(Category)])):max(Days)+1) %>% ungroup m<-df1 %>% group_by(Category,Week) %>% summarize(across(starts_with("DR1"), mean)) m<-subset(m, Week == df1$Week[match(ymd(dmda), ymd(df1$date2))] & Category == CategoryChosse)$DR1 maxrange <- range(min(0, datas$Numbers, na.rm = TRUE), na.rm = TRUE) maxrange[2] <- maxrange[2] - (maxrange[2] %%10) + 35 max<-max(0, datas$Days, na.rm = TRUE)+1 plot(Numbers ~ Days, xlim= c(0,max), ylim= c(0,maxrange[2]), xaxs='i',data = datas,main = paste0(dmda, "-", CategoryChosse)) if (nrow(datas)<=2){ abline(h=m,lwd=2) points(0, m, col = "red", pch = 19, cex = 2, xpd = TRUE) text(.1,m+ .5, round(m,1), cex=1.1,pos=4,offset =1,col="black")} else if(any(table(datas$Numbers) >= 3) & length(unique(datas$Numbers)) == 1){ yz <- unique(datas$Numbers) lines(c(0,datas$Days), c(yz, datas$Numbers), lwd = 2) points(0, yz, col = "red", pch = 19, cex = 2, xpd = TRUE) text(.1,yz+ .5,round(yz,1), cex=1.1,pos=4,offset =1,col="black")} else{ mod <- nls(Numbers ~ b1*Days^2+b2,start = list(b1 = 0,b2 = 0),data = datas, algorithm = "port") new.data <- data.frame(Days = with(datas, seq(min(Days),max(Days),len = 45))) new.data <- rbind(0, new.data) lines(new.data$Days,predict(mod,newdata = new.data),lwd=2) coef<-coef(mod)[2] points(0, coef, col="red",pch=19,cex = 2,xpd=TRUE) text(.99,coef + 1,max(0, round(coef,1)), cex=1.1,pos=4,offset =1,col="black") } } ui <- fluidPage( useShinyjs(), shiny::navbarPage(theme = shinytheme("flatly"), collapsible = TRUE, br(), tabPanel("", sidebarLayout( sidebarPanel( br(), uiOutput('fileInput'), br(), uiOutput("date"), uiOutput("mycode"), actionButton("reset", "Reset"), br(), ), mainPanel( tabsetPanel( tabPanel("", plotOutput("graph",width = "100%", height = "600") ) ), )) ))) server <- function(input, output,session) { # 用reactiveVal存储数据,方便手动重置 data <- reactiveVal(NULL) # 监听文件上传事件,加校验逻辑 observeEvent(input$file, { if (is.null(input$file)) { data(NULL) return() } # 校验1:文件后缀是否为xlsx file_ext <- tolower(tools::file_ext(input$file$name)) if (file_ext != "xlsx") { showNotification("您上传的文件不正确", type = "error", duration = 3) data(NULL) return() } # 读取文件 df3 <- tryCatch(read_excel(input$file$datapath), error = function(e) { showNotification("您上传的文件不正确", type = "error", duration = 3) return(NULL) }) if (is.null(df3)) { data(NULL) return() } # 校验2:列名是否符合要求 required_cols <- c("date1", "date2", "Category", "Week", "DR1") if (!all(required_cols %in% colnames(df3)) || length(grep("^DR0", colnames(df3))) == 0) { showNotification("您上传的文件不正确", type = "error", duration = 3) data(NULL) return() } # 校验通过,赋值数据 data(df3) }) output$fileInput <- renderUI({ fileInput("file",h4("Import file"), multiple = T, accept = ".xlsx") }) output$date <- renderUI({ req(data()) all_dates <- seq(as.Date('2021-01-01'), as.Date('2021-01-15'), by = "day") disabled <- as.Date(setdiff(all_dates, as.Date(data()$date2)), origin = "1970-01-01") dateInput(input = "date2", label = h4("Data"), min = min(data()$date2), value = min(data()$date2), format = "dd-mm-yyyy", datesdisabled = disabled) }) output$mycode <- renderUI({ req(input$date2, data()) df1 <- data() df2 <- df1[as.Date(df1$date2) %in% input$date2,] selectInput("code", label = h4("Category"),choices=unique(df2$Category)) }) output$graph <- renderPlot({ req(input$date2, input$code, data()) f1(data(), as.character(input$date2), as.character(input$code)) }) # 重置逻辑 observeEvent(input$reset, { # 清空数据 data(NULL) # 重置文件上传组件 reset("fileInput") }) } shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

