新手求助:RShiny训练跑量计算应用开发问题
RShiny训练跑量计算应用问题
我是RShiny新手,正在开发一款计算球员训练期间总跑米数的应用。现有包含各训练项每分钟米数的CSV文件,希望根据所选训练项及时长计算总跑量,但不知如何从CSV中提取选中训练项的对应数据并乘以所选分钟数,当前编写的代码无法正常运行,具体代码如下:
ui <- fluidPage( titlePanel("Practice Planner"), sidebarLayout( sidebarPanel( numericInput("num", h3("Number of Drills"), value = 1) ), mainPanel( selectInput("DrillName", label = "Choose a Drill:", choices = unique(MyData$Drill), selected = NULL, multiple = FALSE), sliderInput("slider11", label = h3("Slider"), min = 0, max = 60, value = 0), conditionalPanel( condition = "input.num > '1'", selectInput("Drill Name", label = "Choose a Drill:", choices = unique(MyData$Drill), selected = NULL, multiple = FALSE), sliderInput("slider1", label = h3("Slider"), min = 0, max = 60, value = 0)), conditionalPanel( condition = "input.num > '2'", selectInput("Drill Name", label = "Choose a Drill:", choices = unique(MyData$Drill), selected = NULL, multiple = FALSE), sliderInput("slider1", label = h3("Slider"), min = 0, max = 60, value = 0)), conditionalPanel( condition = "input.num > '3'", selectInput("Drill Name", label = "Choose a Drill:", choices = unique(MyData$Drill), selected = NULL, multiple = FALSE), sliderInput("slider1", label = h3("Slider"), min = 0, max = 60, value = 0)), conditionalPanel( condition = "input.num > '4'", selectInput("Drill Name", label = "Choose a Drill:", choices = unique(MyData$Drill), selected = NULL, multiple = FALSE), sliderInput("slider1", label = h3("Slider"), min = 0, max = 60, value = 0)), conditionalPanel( condition = "input.num > '5'", selectInput("Drill Name", label = "Choose a Drill:", choices = unique(MyData$Drill), selected = NULL, multiple = FALSE), sliderInput("slider1", label = h3("Slider"), min = 0, max = 60, value = 0)), textOutput("MpM1") ) ) ) # Define server logic ---- server <- function(input, output, session) { output$MpM1 <- renderText({ chosendrill <- (input$DrillName) MpM <- unique.data.frame(MyData$MetersPerMinute) MpM1 <- (MpM[[chosendrill]]) * (input$slider11) }) } # Create Shiny app ---- shinyApp(ui = ui, server = server)
问题排查与修复方案
核心问题分析
- 输入控件ID重复:多个
selectInput和sliderInput使用相同ID(如"Drill Name"、"slider1"),Shiny要求每个输入控件ID唯一,否则会导致数据读取混乱。 - 数据提取逻辑错误:服务器端用
unique.data.frame(MyData$MetersPerMinute)只能得到单列数据,无法通过训练项名称索引对应值。 - 条件面板判断错误:
condition = "input.num > '1'"将数字与字符串比较,应改为input.num > 1。 - 多训练项计算缺失:原代码仅处理第一个训练项,未实现多训练项跑量汇总。
修复后的完整代码
假设CSV文件包含两列:Drill(训练项名称)、MetersPerMinute(每分钟米数),修复后的代码如下:
# 先读取CSV数据,放在代码最前端 MyData <- read.csv("你的训练数据文件路径.csv", stringsAsFactors = FALSE) ui <- fluidPage( titlePanel("训练计划跑量计算器"), sidebarLayout( sidebarPanel( numericInput("num", h3("训练项数量"), value = 1, min = 1, max = 5) ), mainPanel( # 第一个训练项,ID唯一 selectInput("DrillName1", label = "选择训练项1:", choices = unique(MyData$Drill), selected = NULL), sliderInput("slider1", label = h3("训练时长(分钟):"), min = 0, max = 60, value = 0), # 后续训练项,每个控件ID唯一 conditionalPanel( condition = "input.num > 1", selectInput("DrillName2", label = "选择训练项2:", choices = unique(MyData$Drill), selected = NULL), sliderInput("slider2", label = h3("训练时长(分钟):"), min = 0, max = 60, value = 0) ), conditionalPanel( condition = "input.num > 2", selectInput("DrillName3", label = "选择训练项3:", choices = unique(MyData$Drill), selected = NULL), sliderInput("slider3", label = h3("训练时长(分钟):"), min = 0, max = 60, value = 0) ), conditionalPanel( condition = "input.num > 3", selectInput("DrillName4", label = "选择训练项4:", choices = unique(MyData$Drill), selected = NULL), sliderInput("slider4", label = h3("训练时长(分钟):"), min = 0, max = 60, value = 0) ), conditionalPanel( condition = "input.num > 4", selectInput("DrillName5", label = "选择训练项5:", choices = unique(MyData$Drill), selected = NULL), sliderInput("slider5", label = h3("训练时长(分钟):"), min = 0, max = 60, value = 0) ), h3("总跑量(米):"), textOutput("TotalMeters") ) ) ) server <- function(input, output, session) { # 响应式计算总跑量 total_meters <- reactive({ total <- 0 # 根据选择的训练项数量循环计算 for (i in 1:input$num) { drill_name <- input[[paste0("DrillName", i)]] minutes <- input[[paste0("slider", i)]] # 匹配训练项对应的每分钟米数 meters_per_min <- MyData$MetersPerMinute[MyData$Drill == drill_name] # 累加跑量 total <- total + (meters_per_min * minutes) } total }) # 输出总跑量 output$TotalMeters <- renderText({ total_meters() }) } shinyApp(ui = ui, server = server)
关键修复点说明
- 唯一控件ID:给每个输入控件设置唯一ID(如
DrillName1、slider1),确保服务器能准确读取对应输入值。 - 正确数据提取:用
MyData$MetersPerMinute[MyData$Drill == drill_name]精准匹配选中训练项的每分钟米数。 - 条件判断修正:将条件面板的字符串比较改为数字比较,确保面板触发逻辑正确。
- 多训练项汇总:通过循环遍历选中的训练项数量,逐个计算跑量并累加得到总跑量。
- 数据读取前置:在UI和服务器逻辑前读取CSV数据,避免加载时出现
MyData未定义的错误。
内容的提问来源于stack exchange,提问作者Sonia
相关产品推荐
相关产品推荐

