You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 05:24:03