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

Shiny绘图报错:seq.default中'from'需为有限数值,求解决方案

解决Shiny正态分布绘图报错问题

问题根源

报错'from' must be a finite number以及绘图不显示,核心有两个原因:

  1. 序列生成失败:当选择"upper"或"lower"尾时,score_b被赋值为NA,直接用min(score_a, score_b, ...)和max(...)会返回NA,导致seq()函数无法生成有效的x序列。
  2. 缺失密度值定义:ggplot的geom_line和geom_area中没有指定y轴对应的正态分布密度值,图形无法渲染。

修复步骤

  1. 忽略NA值计算序列范围:在min()和max()中添加na.rm=TRUE参数,跳过NA值计算有效范围。
  2. 定义正态分布密度值:计算x对应的正态分布密度y,为ggplot提供y轴数据。
  3. 优化双尾逻辑:双尾模式下确保score_a小于score_b,避免阴影区域和p值计算混乱。

修正后的完整代码

library(shiny)
library(ggplot2)

# Define UI
ui <- fluidPage(
  titlePanel("Normal Distribution Calculator"),
  
  sidebarLayout(
    sidebarPanel(
      numericInput("mean", "Mean:", value = 0),
      numericInput("sd", "Standard Deviation:", value = 1),
      numericInput("score_a", "Score A:", value = -1),
      conditionalPanel(
        condition = "input.tail == 'both'",
        numericInput("score_b", "Score B:", value = 1)
      ),
      selectInput("tail", "Tail(s) to find:", choices = c("upper", "lower", "both")),
      actionButton("calculate", "Calculate")
    ),
    
    mainPanel(
      plotOutput("plot"),
      textOutput("p_value")
    )
  )
)

# Define server logic
server <- function(input, output) {
  output$p_value <- renderText({
    req(input$calculate)
    
    mean_val <- input$mean
    sd_val <- input$sd
    score_a <- input$score_a
    score_b <- ifelse(input$tail == "both", input$score_b, NA)
    
    if (input$tail == "upper") {
      p_value <- pnorm(score_a, mean = mean_val, sd = sd_val, lower.tail = FALSE)
    } else if (input$tail == "lower") {
      p_value <- pnorm(score_a, mean = mean_val, sd = sd_val, lower.tail = TRUE)
    } else {
      # 确保score_a小于score_b,避免p值计算错误
      if(score_a > score_b){
        temp <- score_a
        score_a <- score_b
        score_b <- temp
      }
      p_value <- pnorm(score_a, mean = mean_val, sd = sd_val, lower.tail = TRUE) +
        (1 - pnorm(score_b, mean = mean_val, sd = sd_val, lower.tail = TRUE))
    }
    
    paste("P-value:", round(p_value, 4))
  })
  
  output$plot <- renderPlot({
    req(input$calculate)
    
    mean_val <- input$mean
    sd_val <- input$sd
    score_a <- input$score_a
    score_b <- ifelse(input$tail == "both", input$score_b, NA)
    
    # 处理双尾模式下的score顺序
    if(input$tail == "both" && score_a > score_b){
      temp <- score_a
      score_a <- score_b
      score_b <- temp
    }
    
    # 计算x序列范围,忽略NA值
    x_min <- min(score_a, score_b, mean_val - 4 * sd_val, na.rm = TRUE)
    x_max <- max(score_a, score_b, mean_val + 4 * sd_val, na.rm = TRUE)
    x <- seq(x_min, x_max, length.out = 1000)
    
    # 计算正态分布密度
    y <- dnorm(x, mean = mean_val, sd = sd_val)
    
    ggplot() +
      geom_line(aes(x = x, y = y), color = "blue") +
      # 下尾阴影
      geom_area(aes(x = ifelse((input$tail == "lower" | input$tail == "both") & x <= score_a, x, NA), 
                    y = y), 
                fill = "red", alpha = 0.5) +
      # 上尾阴影
      geom_area(aes(x = ifelse((input$tail == "upper" | input$tail == "both") & x >= score_b, x, NA), 
                    y = y), 
                fill = "green", alpha = 0.5) +
      labs(x = "Score", y = "Density", 
           title = "Normal Distribution with Shaded Areas",
           subtitle = paste("Mean:", mean_val, "SD:", sd_val)) +
      theme_minimal()
  })
}

# Run the application
shinyApp(ui = ui, server = server)

关键修改说明

  • 在min()和max()中添加na.rm=TRUE,确保即使存在NA值也能生成有效的x序列。
  • 定义y = dnorm(x, mean_val, sd_val),为ggplot提供密度值数据。
  • 双尾模式下增加score顺序校验,确保score_a始终小于score_b,避免阴影区域和p值计算错误。
  • 调整双尾模式下的上尾阴影逻辑,使用score_b作为上界,符合双尾检验的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:20:28