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

如何用Shiny响应式函数绘制分位数分类的sf对象地图并解决报错

问题原因与解决代码

你的错误出在这句代码:

labels() <- labels()[1:length(labels()) - 1]

反应式对象(比如labels())不能在反应式上下文(reactive、render函数)外部直接赋值修改,这违反了Shiny的反应式规则,才会抛出"You tried to do something that can only be done from inside a reactive consumer"错误。

另外还有几个潜在问题:

  • 用到了imap_chr但没加载purrr包
  • income_grp存在NA值,需要从选择项中剔除
  • 标签里的%是错误的,pop_est是人口估计数,不是百分比

以下是修正后的完整代码:

library(shiny)
library(sf)
library(tidyverse) # 包含dplyr、ggplot2、purrr等包

# 加载数据并预处理选择项
shp <- rnaturalearth::ne_countries(returnclass = "sf", scale = 'large')
income_choices <- shp %>% 
  pull(income_grp) %>% 
  unique() %>% 
  na.omit() %>% 
  sort()

ui <- bootstrapPage(
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  absolutePanel(top = 10, right = 10,
                selectInput("income", label = "选择收入分组", choices = income_choices)
  ),
  plotOutput("map", width = "100%", height = "100%"),
)

server <- function(input, output, session) {
  
  shp_filtered <- reactive({
    shp %>%
      filter(income_grp == input$income)
  })
  
  quantiles <- reactive({
    shp_filtered() %>%
      pull(pop_est) %>%
      quantile(probs = seq(0, 1, length.out = 4), na.rm = TRUE) %>% 
      as.vector()
  })
  
  # 在reactive内部处理标签,去掉最后一项
  labels <- reactive({
    q <- quantiles()
    imap_chr(q[-length(q)], function(x, idx){
      paste0(round(x, 0), " – ", round(q[idx + 1], 0))
    })
  })
  
  shp_final <- reactive({
    shp_filtered() %>%
      mutate(pop_quantiles = cut(pop_est,
                                  breaks = quantiles(),
                                  labels = labels(),
                                  include.lowest = TRUE))
  })
  
  output$map <- renderPlot({
    shp_final() %>%
      ggplot() +
      geom_sf(aes(fill = pop_quantiles), color = "white", size = 0.1) +
      scale_fill_viridis_d(option = "plasma", name = "人口估计数") +
      theme_void() +
      theme(legend.position = "bottom")
  })
  
}

shinyApp(ui, server)

关键修改说明

  • 把标签的截断逻辑放到labels的reactive内部,通过q[-length(q)]直接生成正确长度的标签,避免外部修改反应式对象
  • 加载tidyverse包统一管理所需的工具包
  • 预处理income_grp的选择项,剔除NA并排序
  • 修正标签文本,去掉错误的%符号
  • 优化地图样式,添加边界线、调整图例位置和颜色方案,更接近示例图效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:58:34