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

R Shiny中散点图轴切换时SelectInput与SliderInput异常问题

问题描述

需要创建可切换坐标轴的散点图,核心需求:

  • 当选择Age或BMI作为X/Y轴时,通过SliderInput调整对应轴的极值
  • 无论是否选中这两个变量(包括仅选中其一的情况),散点图都能正常显示
    当前代码在未选中Age/BMI作为坐标轴时会崩溃,需修复该问题并完善交互逻辑。

解决方案

以下是修改后的完整代码,包含UI补充、Server逻辑修复两部分:

修改后的 ui.R

library(shiny)

dataset <- read.csv("../dataset/HCV-Egy-Data.csv")
# 获取数据集列名作为坐标轴可选变量
axis_options <- colnames(dataset)

departament <- list("d1", "d2")

ui <- fluidPage(
  titlePanel("可切换坐标轴散点图"),
  sidebarLayout(
    sidebarPanel(
      # 坐标轴选择控件
      selectInput("xaxis", "选择X轴变量", choices = axis_options, selected = "Age"),
      selectInput("yaxis", "选择Y轴变量", choices = axis_options, selected = "BMI"),
      
      # Age和BMI的滑块输入(绑定对应轴的范围调整)
      sliderInput("age", "Age范围",
                  min = min(dataset$Age, na.rm = TRUE),
                  max = max(dataset$Age, na.rm = TRUE),
                  value = c(min(dataset$Age, na.rm = TRUE), max(dataset$Age, na.rm = TRUE))),
      sliderInput("bmi", "BMI范围",
                  min = min(dataset$BMI, na.rm = TRUE),
                  max = max(dataset$BMI, na.rm = TRUE),
                  value = c(min(dataset$BMI, na.rm = TRUE), max(dataset$BMI, na.rm = TRUE))),
      
      # 保留原有的其他筛选控件
      selectInput("gender", "Gender", choices = unique(dataset$Gender)),
      checkboxGroupInput("symptoms", "Symptoms", choices = unique(dataset$Symptoms)),
      sliderInput("wbc", "WBC范围",
                  min = min(dataset$WBC, na.rm = TRUE),
                  max = max(dataset$WBC, na.rm = TRUE),
                  value = c(min(dataset$WBC, na.rm = TRUE), max(dataset$WBC, na.rm = TRUE))),
      sliderInput("rbc", "RBC范围",
                  min = min(dataset$RBC, na.rm = TRUE),
                  max = max(dataset$RBC, na.rm = TRUE),
                  value = c(min(dataset$RBC, na.rm = TRUE), max(dataset$RBC, na.rm = TRUE))),
      sliderInput("hgb", "HGB范围",
                  min = min(dataset$HGB, na.rm = TRUE),
                  max = max(dataset$HGB, na.rm = TRUE),
                  value = c(min(dataset$HGB, na.rm = TRUE), max(dataset$HGB, na.rm = TRUE))),
      sliderInput("plat", "Platelet范围",
                  min = min(dataset$Platelet, na.rm = TRUE),
                  max = max(dataset$Platelet, na.rm = TRUE),
                  value = c(min(dataset$Platelet, na.rm = TRUE), max(dataset$Platelet, na.rm = TRUE)))
    ),
    mainPanel(
      textOutput("members"),
      textOutput("selectedValues"),
      fluidRow(
        style = "background-color: #F4F5F5;padding: 5px;",
        helpText("1. 散点图"),
        plotOutput("idiom1scatterplot"),
      ),
      fluidRow(
        style = "background-color: #F4F5F5;padding: 5px;",
        helpText("2. 其他模块"),
      ),
      fluidRow(
        style = "background-color: #F4F5F5;padding: 5px;",
        helpText("3. 其他模块"),
      )
    )
  )
)

修改后的 server.R

#server.R
library(shiny)
library(ggplot2)
library(rlang)

dataset <- read.csv("../dataset/ds-final.csv")

members <- list("Alvaro", "Maxi", "Mikel")

server <- function(input, output, session) {
  output$members <- renderText({
    paste("Authors:", paste(members, collapse = ", "))
  })
  
  output$selectedValues <- renderText({
    paste("Selected values:",
          "\nAge:", input$age[1], "-", input$age[2],
          ",\nGender:", input$gender,
          ",\nBMI:", input$bmi[1], "-", input$bmi[2],
          ",\nSymptoms:", ifelse(length(input$symptoms) > 0, paste(input$symptoms, collapse = ", "), "None"),
          ",\nWBC:", input$wbc[1], "-", input$wbc[2],
          ",\nRBC:", input$rbc[1], "-", input$rbc[2],
          ",\nHGB:", input$hgb[1], "-", input$hgb[2],
          ",\nPlatelet:", input$plat[1], "-", input$plat[2])
  })
  
  output$idiom1scatterplot <- renderPlot({
    x_axis <- sym(input$xaxis)
    y_axis <- sym(input$yaxis)
    
    # 初始化坐标轴范围为当前选中变量的全局极值(解决未选中Age/BMI时变量未定义的问题)
    x_limits <- range(dataset[[input$xaxis]], na.rm = TRUE)
    y_limits <- range(dataset[[input$yaxis]], na.rm = TRUE)
    
    # 当X/Y轴为Age时,用滑块值覆盖默认范围
    if (input$xaxis == "Age") x_limits <- c(input$age[1], input$age[2])
    if (input$yaxis == "Age") y_limits <- c(input$age[1], input$age[2])
    
    # 当X/Y轴为BMI时,用滑块值覆盖默认范围
    if (input$xaxis == "BMI") x_limits <- c(input$bmi[1], input$bmi[2])
    if (input$yaxis == "BMI") y_limits <- c(input$bmi[1], input$bmi[2])
    
    ggplot(data = dataset, aes(x = !!x_axis, y = !!y_axis)) +
      geom_point() +
      theme(legend.position = "top") +
      xlim(x_limits) +
      ylim(y_limits) +
      labs(title = paste("散点图:", input$xaxis, " vs ", input$yaxis), x = input$xaxis, y = input$yaxis)
  })
}

app.R(保持不变)

source("server.R")
source("ui.R")

# Run the app
shinyApp(ui, server)

关键修改说明
  • 补充UI交互控件:添加了坐标轴选择的selectInput,以及Age/BMI对应的SliderInput,解决原UI缺少交互入口导致的input变量不存在问题
  • 初始化坐标轴范围:先给x_limits/y_limits赋值为当前选中变量的全局极值,避免未选中Age/BMI时变量未定义引发的崩溃
  • 简化条件判断:直接用字符串比较代替符号对象比较,逻辑更简洁且避免潜在的类型错误
  • 处理NA值:计算范围时加入na.rm = TRUE,避免数据中存在NA导致的范围计算异常

内容的提问来源于stack exchange,提问作者Maxxss

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:38:12