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

Shiny应用中GoogleVis仪表盘异常:报错$ operator is invalid for atomic vectors

问题排查与修复方案

1. GoogleVis仪表盘弹出独立窗口的问题

在renderGvis函数中调用plot(Gauge)会触发googleVis在独立浏览器窗口渲染图表,这是因为plot()方法本身的行为就是弹出外部窗口。renderGvis的正确用法是直接返回gvis对象,无需调用plot(),修改后即可实现图表嵌入应用内显示。

2. "$ operator is invalid for atomic vectors"错误

这个错误来自两个核心场景:

场景一:地图点击时的浮点精度匹配问题

用df$y == click$lat & df$x == click$lng直接匹配经纬度,会因为浮点型数据的精度误差导致找不到匹配项,进而让location变成空原子向量,后续updateSelectInput中c(input$locations, location)会触发错误。

修复方法:改用dplyr的near()函数进行模糊匹配,允许微小精度误差:

location <- df %>% filter(near(x, click$lng, tol = 1e-4), near(y, click$lat, tol = 1e-4)) %>% pull(locations)

场景二:空输入或多位置选择时的处理缺失

当没有选中任何位置时,locat_data()会返回空数据,传入gvisGauge会引发错误;同时原代码未开启多选支持,地图点击累加选择时会出现逻辑冲突。

修复方法:添加req(input$locations)确保数据非空,给selectizeInput开启multiple = TRUE支持多选。

完整修复后的代码

library(shiny)
library(leaflet)
library(shinydashboard)
library(dplyr)
library(googleVis)

# 构建数据框
locations <- c("A","B","C")
x <- c(36.05617,36.05626,36.05634)
y <- c(-2.1007,-2.05553,-2.01035)
yield <- c(5.86,3.06,1.07)
df <- data.frame(locations,x,y,yield)

################## UI定义 ############################
ui <- shinyUI(dashboardPage(
  title = "Yield Lookup",
  dashboardHeader(title = "Crop Yield (Tonnes per Hectare)", titleWidth = 350),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Map Dashboard", tabName = "datavis",  icon = icon("map", verify_fa = FALSE)),
      menuItem("Select by Location Name", icon = icon("leaf"),
               selectizeInput("locations", "Click on Location", choices = levels(factor(df$locations)), multiple = TRUE)
      )
    )
  ),
  dashboardBody(
    tabItems(
      tabItem(tabName = "datavis",
              h4("Map and Plot"),
              fluidRow(
                box(width= 8,  leafletOutput("map", height = 800)),
                box("Gauge for crop yield by area", width = 4, htmlOutput("myplot"))
              )
      )
    )
  )
))

################## Server定义 ############################
server <- shinyServer(function(input,output, session){
  
  # 筛选选中位置的数据
  locat_data <- reactive({
    req(input$locations) # 确保输入不为空
    df %>% filter(locations %in% input$locations)
  })
  
  # 渲染GoogleVis仪表盘
  output[["myplot"]] <- renderGvis({
    newdf <- locat_data() %>% select(locations, yield)
    gvisGauge(newdf, 
              options=list(min=0, max=6, greenFrom=4,
                           greenTo=6, yellowFrom=2, yellowTo=4,
                           redFrom=0, redTo=2, width=400, height=300))
  })
  
  # 渲染地图
  output$map <- renderLeaflet({
    leaflet(df) %>% 
      addTiles() %>%
      addCircleMarkers(lng = ~x, lat = ~y, layerId = ~locations, color = "blue", radius = 3) %>%
      addCircles(lng = ~x, lat = ~y, weight = 1, radius = 1, label = ~locations)
  })
  
  # 更新选择框(手动选择时)
  observeEvent(input$locations,{
    updateSelectInput(session, "locations", "Click on Locations", 
                      choices = levels(factor(df$locations)), 
                      selected = input$locations)
  })
  
  # 地图点击事件处理
  observeEvent(input$map_marker_click, {
    click <- input$map_marker_click
    # 处理浮点精度问题的坐标匹配
    location <- df %>% 
      filter(near(x, click$lng, tol = 1e-4), near(y, click$lat, tol = 1e-4)) %>% 
      pull(locations)
    
    if(length(location) > 0){ # 确保找到有效位置
      current_selected <- input$locations %||% c()
      new_selected <- unique(c(current_selected, location))
      updateSelectInput(session, "locations", "Click on Location", 
                        choices = levels(factor(df$locations)), 
                        selected = new_selected)
    }
  })
  
})

shinyApp(ui=ui, server = server)

额外优化点

  • 开启selectizeInput的多选支持,匹配地图点击累加选择的逻辑
  • 用unique()避免选择框出现重复选项
  • 删除无用的空响应式对象lo
  • 添加空输入判断,避免无数据时的渲染错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:50:36