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

R Shiny点击Plotly地图后数据表格无数据加载问题求助

解决Shiny+Plotly地图点击后无数据加载的问题

看起来你遇到的核心问题是点击地图标记后无法正确获取对应国家的数据,导致表格只显示框架。我帮你梳理几个关键问题并给出修复方案:

主要问题点

  1. 点击事件的字段获取错误:你用s$y来获取国家名称,但s$y其实返回的是标记的纬度值,不是国家名称,自然匹配不到数据。
  2. 响应式输出的结构错误:把renderDataTable嵌套在自定义函数render_value里并在renderPlotly中调用,不符合Shiny的响应式逻辑,导致表格无法正确监听点击事件的变化。
  3. 事件数据的绑定不明确:需要确保绘图时传递了可用于匹配的国家标识,且event_data的source参数和地图的source完全一致。

修复后的完整代码

Mapbox_Token= '你的Mapbox Token'
library(plotly)
library(readxl)
library(dplyr)
library(shiny)
library(DT)
library(htmlwidgets)

# 加载数据(确保文件路径正确)
data_1 <- read.csv("file.csv")
df <- read.csv("file2.csv")

Sys.setenv("MAPBOX_TOKEN" = Mapbox_Token)

ui <- fluidPage(
  plotlyOutput(outputId = "Plot"),
  DT::dataTableOutput('click_table') # 重命名输出ID更清晰
)

server <- function(input, output, session) {
  output$Plot <- renderPlotly({
    fig <- df %>%
      plot_mapbox(
        lat = ~lat, 
        lon = ~lng,
        split = ~Country, 
        size = 0, 
        type = 'scattermapbox',
        mode = 'markers',
        hoverinfo = "none",
        showlegend = F,
        source = 'subset' # 保持source标识
      ) %>%
      layout(
        title = 'No Of Companies',
        font = list(color='white'),
        plot_bgcolor = '#191A1A', 
        paper_bgcolor = '#191A1A',
        mapbox = list(style = 'dark'),
        legend = list(orientation ='v', font = list(size = 6)),
        margin = list(l = 25, r = 25, b = 75, t = 25, pad = 2)
      ) %>%
      add_annotations(
        text ='Map shows number of companies by country. The size of the circles correspond to the number of companies.',
        x=0.5, y=-0.2, showarrow=FALSE, font=list(color='red')
      ) %>%
      add_markers(
        text = ~paste(
          paste('Country:', Country), 
          paste("Number of Companies:", Name ), 
          paste("Dataset:", Url),
          sep = " <br />"
        ), 
        size = ~Name, 
        hoverinfo = "text",
        marker = list(sizeref=0.1, sizemode="area"),
        showlegend = T,
        customdata = ~Country # 关键:把国家名称存入customdata,方便点击时获取
      ) %>%
      onRender("function(el) {
        el.on('plotly_click', function(d) {
          var url = d.points[0].data.text[d.points[0].pointIndex].split('<br />')[2].split(': ')[1];
          window.open(url);
        });
      }") %>% # 调整URL提取逻辑,因为原来的customdata现在存的是国家,所以从text里提取URL
      config(mapboxAccessToken = Sys.getenv("MAPBOX_TOKEN"))
    
    fig
  })
  
  # 直接定义表格输出,依赖点击事件数据
  output$click_table <- renderDataTable({
    # 获取点击事件数据,指定source为'subset'
    click_event <- event_data("plotly_click", source = "subset")
    
    # 如果没有点击事件,返回空表格;否则筛选对应国家的数据
    if(is.null(click_event)) {
      return(DT::datatable(data.frame(), options = list(dom = 't')))
    } else {
      # 从customdata中获取国家名称
      selected_country <- click_event$customdata
      return(DT::datatable(data_1[data_1$Country == selected_country, ]))
    }
  })
}

shinyApp(ui, server)

关键修改说明

  1. 传递国家标识到点击事件:在add_markers中添加customdata = ~Country,这样点击标记时,event_data就能拿到对应的国家名称,而不是纬度值。
  2. 重构响应式输出结构:把renderDataTable直接放在server顶层,让它直接监听event_data的变化,符合Shiny的响应式机制。
  3. 调整URL提取逻辑:因为我们把customdata用来存国家名称了,所以从标记的text内容中解析URL,确保原来的打开URL功能正常工作。
  4. 空状态处理:当没有点击任何标记时,返回空表格,避免出现错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 19:12:45