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

R Shiny中isTruthy()运行不符合预期,如何实现矩阵条件绘图?

问题根源
  • Shiny的isTruthy()仅判断输入是否存在、非空/非NA/非FALSE,不会区分输入值是UI预设的默认值还是用户手动修改后的值。你取消matrix2的注释后,只要UI中存在该输入控件,isTruthy(input$matrix2)就会永远返回TRUE,导致渲染matrix1的else分支永远不会触发。
  • 你原有逻辑是二选一渲染矩阵结果,也不符合「matrix2有手动输入时两者同时显示」的业务需求。
修改方案

我们需要先记录matrix2的初始默认值,判断用户是否对其做过手动修改,再调整绘图数据的拼接逻辑:

  1. 新增变量存储matrix2的初始默认值,用于比对修改状态
  2. 绘图逻辑调整为:始终生成matrix1的绘图数据,仅当matrix2被手动修改过时,追加其对应的数据
  3. 补充matrix2的行名自动补全监听,和matrix1逻辑对齐
library(dplyr)
library(ggplot2)
library(shiny)
library(shinyMatrix)

sumMat <- function(x){return(rep(sum(x,na.rm = TRUE), 10))}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      matrixInput("matrix1",
                  value = matrix(c(60,5), ncol = 2, dimnames = list(NULL,c("X","Y"))),
                  rows = list(extend = TRUE, delete = TRUE), class = "numeric"),
      # 取消matrix2的注释
      matrixInput("matrix2",
                  label = "Matrix 2 (Value Y applied in Period X):",
                  value = matrix(c(60,5),ncol=2,dimnames=list(NULL,rep("Scenario 1",2))),
                  rows = list(extend = TRUE, delete = TRUE),
                  cols = list(extend = TRUE, delta = 2, delete = TRUE, multiheader = TRUE),
                  class = "numeric"),
    ),
    mainPanel(plotOutput("plot"))  
  )    
)

server <- function(input, output, session){
  # 新增:记录matrix2的初始默认值,用于判断是否被用户修改
  init_mat2 <- isolate(input$matrix2)
  
  observeEvent(input$matrix1, {
    tmpMat1 <- input$matrix1
    if(any(rownames(input$matrix1) == "")){rownames(tmpMat1) <- paste("Row", seq_len(nrow(input$matrix1)))}
    updateMatrixInput(session, inputId = "matrix1", value = tmpMat1)
  })
  
  # 新增:matrix2的行名自动补全逻辑,和matrix1对齐
  observeEvent(input$matrix2, {
    tmpMat2 <- input$matrix2
    if(any(rownames(input$matrix2) == "")){rownames(tmpMat2) <- paste("Row", seq_len(nrow(input$matrix2)))}
    updateMatrixInput(session, inputId = "matrix2", value = tmpMat2)
  })
  
  plotData <- reactive({
    tryCatch({
      # 始终先生成matrix1的绘图数据
      plot_df <- tibble(Scenario = "Matrix1-Scenario1", X = seq_len(10),Y = sumMat(input$matrix1))
      
      # 仅当matrix2被手动修改过,才追加它的绘图数据
      # 用identical判断当前值和初始值是否完全一致,不一致则判定为有手动输入
      if(isTruthy(input$matrix2) && !identical(input$matrix2, init_mat2)){
        mat2_df <- lapply(seq_len(ncol(input$matrix2)/2), 
                          function(i){
                            tibble(Scenario = paste0("Matrix2-",colnames(input$matrix2)[i*2-1]),
                                   X = seq_len(10),Y = sumMat(input$matrix2[,(i*2-1):(i*2), drop = FALSE]))
                          }) %>% bind_rows()
        plot_df <- bind_rows(plot_df, mat2_df)
      }
      return(plot_df)
    }, error = function(e) NULL)
  })
  
  output$plot <- renderPlot({
    req(plotData())
    plotData() %>% ggplot() + geom_line(aes(x = X, y = Y, colour = as.factor(Scenario)))
  })
}

shinyApp(ui, server)

如果不需要同时显示两个矩阵的结果,只需要「有手动修改的matrix2就显示它,否则显示matrix1」,只需要把plotData里的逻辑改回二选一即可,判断条件保留!identical(input$matrix2, init_mat2)就行。

内容的提问来源于stack exchange,提问作者Curious Jorge - user9788072

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:06:11