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

开发R Shiny应用:上传Nodes和Links CSV生成桑基图失败排查

问题诊断与修复方案

你的Shiny应用中文件上传和数据展示正常,但桑基图无法生成,核心问题在于响应式对象的空值处理和渲染逻辑的语法问题,以下是具体修复步骤:

主要问题点

  • 未上传文件时,links()和nodes()返回空字符串"",但sankeyNetwork要求传入数据框,空字符串会直接导致渲染失败。
  • output$plot的赋值多了一层冗余大括号,不符合Shiny的输出渲染语法规范。
  • 读取CSV时重复调用read.csv,既低效又可能引发潜在的数据不一致问题。

修改后的完整代码

library(shiny)
library(DT)
library(readxl)
library(highcharter)
library(dplyr)
library(data.table)
library(networkD3)

ui = fluidPage(
  titlePanel("Sankey"),
  fileInput("link", "Select links file"),
  fileInput("node", "Select nodes file"),
  DT::dataTableOutput("VLout"),
  DT::dataTableOutput("VNout"),
  sankeyNetworkOutput("plot")
)

server <- function(input, output) {
  links <- reactive({
    if (is.null(input$link)) {
      # 返回对应结构的空数据框而非空字符串
      return(data.frame(Source = integer(), Target = integer(), Value = numeric()))
    }
    # 仅读取一次CSV,避免重复IO操作
    link_data <- read.csv(input$link$datapath)
    data.frame(
      Source = link_data$Source,
      Target = link_data$Target,
      Value = link_data$Value,
      check.names = FALSE
    )
  })
  
  nodes <- reactive({
    if (is.null(input$node)) {
      # 返回对应结构的空数据框而非空字符串
      return(data.frame(Name = character()))
    }
    # 仅读取一次CSV
    node_data <- read.csv(input$node$datapath)
    data.frame(Name = node_data$Name, check.names = FALSE)
  })
  
  output$VLout <- DT::renderDataTable({
    links()
  })
  
  output$VNout <- DT::renderDataTable({
    nodes()
  }) 
  
  # 移除冗余大括号,遵循Shiny渲染语法直接赋值
  output$plot <- renderSankeyNetwork({
    # 仅当两个文件都上传且有数据时才生成桑基图
    if (nrow(links()) == 0 || nrow(nodes()) == 0) {
      return(NULL)
    }
    sankeyNetwork(
      Links = links(), 
      Nodes = nodes(), 
      Source = "Source", 
      Target = "Target", 
      Value = "Value", 
      NodeID = "Name", 
      sinksRight = FALSE, 
      fontSize = 16, 
      nodeWidth = 45, 
      nodePadding = 15, 
      margin = list(left = 175, top = 100, right = 175, bottom = 100)
    )           
  })
}

shinyApp(ui = ui, server = server)

关键修改说明

  1. 空值处理优化:未上传文件时返回对应结构的空数据框,确保sankeyNetwork始终接收合法的数据类型,避免因参数类型错误导致渲染失败。
  2. 渲染逻辑修正:移除output$plot赋值时的多余大括号,严格遵循Shiny的输出渲染语法规则。
  3. 性能与稳定性优化:读取CSV文件仅调用一次read.csv,避免重复读取同一文件造成的资源浪费和潜在数据问题。
  4. 增加有效性判断:在渲染桑基图前检查数据框行数,确保只有两个文件都上传且包含有效数据时才生成图表,避免无效渲染操作。

额外注意事项

确保你的Links文件中Source和Target列是从0开始的整数类型(对应Nodes数据框中节点的索引)。如果上传的文件中是字符型节点名称,需要先将其映射为整数索引,示例代码如下:

# 字符型节点名称转索引的示例逻辑
links <- reactive({
  if (is.null(input$link)) {
    return(data.frame(Source = integer(), Target = integer(), Value = numeric()))
  }
  link_data <- read.csv(input$link$datapath)
  node_names <- nodes()$Name
  # 将字符型节点名称映射为从0开始的索引
  link_data$Source <- match(link_data$Source, node_names) - 1
  link_data$Target <- match(link_data$Target, node_names) - 1
  link_data
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:10:25