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

R Shiny无法显示预期绘图,关闭应用后才在RStudio显示的问题

问题:Shiny应用中无法显示collapsibleTree绘图,关闭后才在RStudio绘图区出现

我是R Shiny新手,想要开发一款读取Excel文件、处理数据框并根据指定ID输出绘图的应用。提供的代码在非Shiny环境下可正常运行,但在Shiny应用中无法显示预期绘图,关闭应用后绘图才会出现在RStudio的绘图区域,请问我哪里操作有误?

原代码

library(shiny)
library(readxl)
library(ggenealogy)
library(ggplot2)
library(collapsibleTree)

datos = read_xlsx("file.xlsx", sheet = 1)
'%!in%' = function(x,y)!('%in%'(x,y))

ui <- fluidPage(
  titlePanel("Buscar genealogía"),
  
  sidebarLayout(
    sidebarPanel(
      helpText("Search dendrogram for a given ID"),
      
      textInput("bidi", 
                  label = "Write ID:",
                  value = "PL1804160067"),
    ),
    
    mainPanel(
      plotOutput("grafica")
    )
  )
)

server <- function(input, output) {
  
  output$grafica <- renderPlot({
    
    grafico = plotAncDes(input$bidi, datos, 9, 9)
    datos2 = grafico$data
    
    if ("ancestor" %in% datos2$type){
      ancestros = datos2[datos2$type == "ancestor",]
      n_ancestros = nrow(ancestros)
      generaciones = sort(unique(datos2$genside))
      rows_final = nrow(datos2[datos2$genside == 1,])
      final = data.frame(matrix(ncol = length(generaciones), nrow = rows_final))
      colnames(final) = generaciones
      n_generaciones = length(which(generaciones > 0))
      for (n_ancestro in 1:ncol(final)){
        if (as.numeric(colnames(final)[n_ancestro]) < 0){
          final[, n_ancestro] = datos2$label[which(datos2$genside == colnames(final)[n_ancestro])]
        }
      }
      final[, "0"] = input$bidi
      hijos = getChild(input$bidi, datos)
      final[, "1"] = hijos
      
      
      generacion = 1
      if (max(generaciones) - generacion > 0){
        quedan_generaciones = TRUE  
      }
      else {
        quedan_generaciones = FALSE 
      }
      while (quedan_generaciones){
        for (muestra in unique(final[, as.character(generacion)])){
          nuevos_hijos = getChild(muestra, datos)
          if (length(nuevos_hijos > 0)){
            subdataset = final[which(final[, as.character(generacion)] == muestra),]
            fila_copiar = subdataset
            for (i in 1:(length(nuevos_hijos) -1)){
              subdataset = rbind(subdataset, fila_copiar)
            }
            subdataset[, as.character(generacion + 1)] = nuevos_hijos
            final = final[-which(final[, as.character(generacion)] == muestra),]
            final = rbind(final, subdataset)
          }
        }
        generacion = generacion + 1
        if (generacion > max(generaciones)){
          quedan_generaciones = FALSE
        }
      }
    }
    
    if ("ancestor" %!in% datos2$type){
      generaciones = sort(unique(datos2$genside))
      rows_final = nrow(datos2[datos2$genside == 1,])
      final = data.frame(matrix(ncol = length(generaciones), nrow = rows_final))
      colnames(final) = generaciones
      n_generaciones = length(which(generaciones > 0))
      
      final[, "0"] = input$bidi
      hijos = getChild(input$bidi, datos)
      final[, "1"] = hijos
      
      
      generacion = 1
      if (max(generaciones) - generacion > 0){
        quedan_generaciones = TRUE  
      }
      else {
        quedan_generaciones = FALSE 
      }
      while (quedan_generaciones){
        for (muestra in unique(final[, as.character(generacion)])){
          nuevos_hijos = getChild(muestra, datos)
          if (length(nuevos_hijos > 0)){
            subdataset = final[which(final[, as.character(generacion)] == muestra),]
            fila_copiar = subdataset
            for (i in 1:(length(nuevos_hijos) - 1)){
              subdataset = rbind(subdataset, fila_copiar)
            }
            subdataset[, as.character(generacion + 1)] = nuevos_hijos
            final = final[-which(final[, as.character(generacion)] == muestra),]
            final = rbind(final, subdataset)
          }
        }
        generacion = generacion + 1
        if (generacion > max(generaciones)){
          quedan_generaciones = FALSE
        }
      }
    }
    
    collapsibleTree(final, hierarchy = colnames(final))

  })
  
}

shinyApp(ui, server)

问题原因与解决方案

核心问题

collapsibleTree()返回的是HTML交互式控件(htmlwidgets对象),而非传统的R图形对象(如ggplot2或基础绘图)。你当前使用的renderPlot()和plotOutput()是专门用于渲染传统R图形的,无法正确处理htmlwidgets类型的输出,导致绘图无法在Shiny界面显示,只能在关闭应用后输出到RStudio的绘图区。

修改步骤

  1. UI端:将plotOutput("grafica")替换为htmlOutput("grafica")(或使用collapsibleTreeOutput("grafica"),两者效果一致)。
  2. Server端:将renderPlot()替换为renderUI(),确保返回collapsibleTree生成的对象。

修改后的完整代码

library(shiny)
library(readxl)
library(ggenealogy)
library(ggplot2)
library(collapsibleTree)

datos = read_xlsx("file.xlsx", sheet = 1)
'%!in%' = function(x,y)!('%in%'(x,y))

ui <- fluidPage(
  titlePanel("Buscar genealogía"),
  
  sidebarLayout(
    sidebarPanel(
      helpText("Search dendrogram for a given ID"),
      
      textInput("bidi", 
                  label = "Write ID:",
                  value = "PL1804160067"),
    ),
    
    mainPanel(
      # 替换为htmlOutput
      htmlOutput("grafica")
    )
  )
)

server <- function(input, output) {
  
  # 替换为renderUI
  output$grafica <- renderUI({
    
    grafico = plotAncDes(input$bidi, datos, 9, 9)
    datos2 = grafico$data
    
    if ("ancestor" %in% datos2$type){
      ancestros = datos2[datos2$type == "ancestor",]
      n_ancestros = nrow(ancestros)
      generaciones = sort(unique(datos2$genside))
      rows_final = nrow(datos2[datos2$genside == 1,])
      final = data.frame(matrix(ncol = length(generaciones), nrow = rows_final))
      colnames(final) = generaciones
      n_generaciones = length(which(generaciones > 0))
      for (n_ancestro in 1:ncol(final)){
        if (as.numeric(colnames(final)[n_ancestro]) < 0){
          final[, n_ancestro] = datos2$label[which(datos2$genside == colnames(final)[n_ancestro])]
        }
      }
      final[, "0"] = input$bidi
      hijos = getChild(input$bidi, datos)
      final[, "1"] = hijos
      
      
      generacion = 1
      if (max(generaciones) - generacion > 0){
        quedan_generaciones = TRUE  
      }
      else {
        quedan_generaciones = FALSE 
      }
      while (quedan_generaciones){
        for (muestra in unique(final[, as.character(generacion)])){
          nuevos_hijos = getChild(muestra, datos)
          if (length(nuevos_hijos > 0)){
            subdataset = final[which(final[, as.character(generacion)] == muestra),]
            fila_copiar = subdataset
            for (i in 1:(length(nuevos_hijos) -1)){
              subdataset = rbind(subdataset, fila_copiar)
            }
            subdataset[, as.character(generacion + 1)] = nuevos_hijos
            final = final[-which(final[, as.character(generacion)] == muestra),]
            final = rbind(final, subdataset)
          }
        }
        generacion = generacion + 1
        if (generacion > max(generaciones)){
          quedan_generaciones = FALSE
        }
      }
    }
    
    if ("ancestor" %!in% datos2$type){
      generaciones = sort(unique(datos2$genside))
      rows_final = nrow(datos2[datos2$genside == 1,])
      final = data.frame(matrix(ncol = length(generaciones), nrow = rows_final))
      colnames(final) = generaciones
      n_generaciones = length(which(generaciones > 0))
      
      final[, "0"] = input$bidi
      hijos = getChild(input$bidi, datos)
      final[, "1"] = hijos
      
      
      generacion = 1
      if (max(generaciones) - generacion > 0){
        quedan_generaciones = TRUE  
      }
      else {
        quedan_generaciones = FALSE 
      }
      while (quedan_generaciones){
        for (muestra in unique(final[, as.character(generacion)])){
          nuevos_hijos = getChild(muestra, datos)
          if (length(nuevos_hijos > 0)){
            subdataset = final[which(final[, as.character(generacion)] == muestra),]
            fila_copiar = subdataset
            for (i in 1:(length(nuevos_hijos) - 1)){
              subdataset = rbind(subdataset, fila_copiar)
            }
            subdataset[, as.character(generacion + 1)] = nuevos_hijos
            final = final[-which(final[, as.character(generacion)] == muestra),]
            final = rbind(final, subdataset)
          }
        }
        generacion = generacion + 1
        if (generacion > max(generaciones)){
          quedan_generaciones = FALSE
        }
      }
    }
    
    # 返回collapsibleTree对象
    collapsibleTree(final, hierarchy = colnames(final))

  })
  
}

shinyApp(ui, server)

额外说明

如果偏好使用专门的控件,也可以将UI端的htmlOutput替换为collapsibleTreeOutput("grafica"),Server端的renderUI替换为renderCollapsibleTree,功能完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 13:47:06