如何调整Shiny应用中tabPanel的绘图逻辑避免代码冗余
解决方案
核心思路
- 无需新增f2函数导致代码冗余,只需要给现有f1函数新增一个模式控制参数,通过参数切换两类图表的差异配置,公共逻辑完全复用
具体修改点
- 为f1函数新增
graph_type参数,默认值为"graph1",不影响原有Graph1的调用逻辑 - 针对两类图表的差异点(列命名、切片变量、plot参数、拟合公式、新数据集构造)做动态适配
- 服务端渲染Graph2时,调用f1传入
graph_type = "graph2"即可
修改后的完整代码
library(shiny) library(shinythemes) library(dplyr) library(tidyverse) library(lubridate) Test <- structure( list(date1= c("2021-06-28","2021-06-28"), date2 = c("2021-07-01","2021-07-01"), Category = c("FDE","ABC"), Week= c("Friday","Monday"), DR1 = c(14,11), DR01 = c(14,12), DR02= c(14,12),DR03= c(19,15), DR04 = c(15,14),DR05 = c(15,14), DR06 = c(12,14)), class = "data.frame", row.names = c(NA, -2L)) f1 <- function(df1, dmda, CategoryChosse, graph_type = "graph1") { 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")) 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)) # 动态配置差异参数 if (graph_type == "graph1") { x_col <- "Days" y_col <- "Numbers" x_lim <- c(0,45) y_lim <- c(0,30) } else { x_col <- "Reserv" y_col <- "Weekdays" x_lim <- c(0,80) y_lim <- c(0,50) } colnames(datas)[-1]<-c(x_col, y_col) max_x_val <- max(datas[[x_col]]) if(as.Date(dmda) < min(as.Date(df1$date1))){ datas <- datas %>% group_by(Category) %>% slice(1:max_x_val+1) %>% ungroup }else{ datas <- datas %>% group_by(Category) %>% slice((as.Date(dmda) - min(as.Date(df1$date1) [ df1$Category == first(Category)])):max_x_val+1) %>% ungroup } # 动态生成绘图公式 plot_formula <- reformulate(x_col, y_col) plot(plot_formula, xlim= x_lim, ylim= y_lim, xaxs='i',data = datas,main = paste0(dmda, "-", CategoryChosse)) # 动态生成拟合公式 fit_formula <- as.formula(paste0(y_col, " ~ b1*", x_col, "^2+b2")) model <- nls(fit_formula,start = list(b1 = 0,b2 = 0),data = datas, algorithm = "port") new.data <- data.frame(x = with(datas, seq(min(.data[[x_col]]),max(.data[[x_col]]),len = 45))) colnames(new.data) <- x_col new.data <- rbind(0, new.data) lines(new.data[[x_col]],predict(model,newdata = new.data),lwd=2) coef_val<-coef(model)[2] points(0, coef_val, col="red",pch=19,cex = 2,xpd=TRUE) } ui <- fluidPage( ui <- shiny::navbarPage(theme = shinytheme("flatly"), collapsible = TRUE, br(), tabPanel("", sidebarLayout( sidebarPanel( uiOutput("date"), uiOutput("mycode"), ), mainPanel( tabsetPanel( tabPanel("Graph1", plotOutput("graph",width = "100%", height = "600")), tabPanel("Graph2", plotOutput("graph2",width = "100%", height = "600")) ) ) )) )) server <- function(input, output,session) { data <- reactive(Test) 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), max = max(data()$date2), value = min(data()$date2)) }) output$mycode <- renderUI({ req(input$date2) 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) f1(data(),as.character(input$date2),as.character(input$code), graph_type = "graph1") }) output$graph2 <- renderPlot({ req(input$date2,input$code) f1(data(),as.character(input$date2),as.character(input$code), graph_type = "graph2") }) } shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

