R Shiny如何访问重复Horizon数据实现元素浓度交互箱线图
错误原因
- 你代码中
Analyse %>% dplyr::select(!!!input$lith)逻辑错误:select()是筛选数据框列的函数,而input$lith是Horizon列的取值(比如"Horizon A"),不是列名,因此触发列不存在的报错。 - 要实现多选元素同步更新的需求,需要先将宽格式的元素数据转为长格式,再按选中的层位、元素做行过滤。
完整可运行修改版代码
library(shiny) library(shinyWidgets) library(dplyr) library(ggplot2) library(viridis) library(hrbrthemes) library(rio) library(tidyr) # 构造示例数据 set.seed(1234) A = tibble ( Horizon = ("Horizon A"), Depth = seq(0, 2.6, 0.2), Element_1 = abs(round(rnorm(14), 2)), Element_2 = abs(round(rnorm(14), 2)), Element_3 = abs(round(rnorm(14), 2)) ) B = tibble ( Horizon = ("Horizon B"), Depth = seq(2.8, 43.8, 0.33), Element_1 = abs(round(rnorm(125), 2)), Element_2 = abs(round(rnorm(125), 2)), Element_3 = abs(round(rnorm(125), 2)) ) C = tibble ( Horizon = ("Horizon C"), Depth = seq(44, 50, 0.6), Element_1 = abs(round(rnorm(11), 2)), Element_2 = abs(round(rnorm(11), 2)), Element_3 = abs(round(rnorm(11), 2)) ) Analyse = rbind(A, B, C) # UI部分 ui <- fluidPage( titlePanel(title = h4("土壤/岩石层元素浓度对比工具", align = "center")), sidebarLayout( sidebarPanel( pickerInput( inputId = "lith", label = "选择层位", choices = unique(Analyse$Horizon), selected = NULL, multiple = TRUE, options = list("max-options" = 3, "max-options-text" = "最多可选3个层位") ), br(), pickerInput( inputId = "element", label = "选择元素", choices = colnames(Analyse)[3:5], multiple = TRUE, options = list(`actions-box` = TRUE) ) ), mainPanel( tabsetPanel(type = "tab", tabPanel("箱线图", plotOutput("box", height = 600, width = 900))) ) ) ) # 服务端部分 server <- function(input, output, session) { output$box = renderPlot({ # 校验:必须至少选1个层位和1个元素才绘图 req(input$lith, input$element) # 数据处理:转长格式+按选中值过滤 plot_data <- Analyse %>% pivot_longer(cols = Element_1:Element_3, names_to = "Element", values_to = "Values") %>% filter(Horizon %in% input$lith, Element %in% input$element) # 基础绘图 p <- ggplot(plot_data, aes(x= "", y= Values)) + geom_boxplot(notch = TRUE, color = "#e9ecef", fill="#69b3a2", outlier.colour = "red", width = 0.6)+ stat_summary(fun = "mean", color = "black", shape = 8) + geom_jitter(alpha = 0.8, width = 0.2, height = 0, color = "orange") + labs(title = "元素浓度分布箱线图", subtitle = "黑色星号:平均值\n红色点:异常值", caption = paste("选中层位:", paste(input$lith, collapse = ", ")))+ theme_ipsum() + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank(), plot.title = element_text(size=15)) # 自动适配分面规则 if(length(input$lith) > 1 & length(input$element) == 1){ # 多选层位+单选元素:按层位分面 p <- p + facet_wrap(~Horizon, scales = 'free_y', nrow = 1) } else if(length(input$element) > 1 & length(input$lith) == 1){ # 单选层位+多选元素:按元素分面 p <- p + facet_wrap(~Element, scales = 'free_y', nrow = 1) } return(p) }, res = 96) } shinyApp(ui, server)
实现功能说明
- 单选层位+单选元素:展示对应单组元素浓度的箱线图
- 单选层位+多选元素:自动按元素分面,同步展示同层位下多个元素的浓度分布
- 多选层位+单选元素:自动按层位分面,同步展示同一元素在不同层位的浓度分布
内容的提问来源于stack exchange,提问作者retep
相关产品推荐
相关产品推荐

