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

新手求助: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:10:24