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

开发巴西巴伊亚州道路事故Shiny可视化应用时Facet报错:latitude < -90

解决Shiny中SF分面时的纬度异常错误

这个错误我之前处理巴西空间数据时也碰到过几次,大概率不是Facet操作直接修改了数据值,而是分面过程中图层的坐标系、数据类型或者动态渲染逻辑出了问题。下面是几个最常见的原因和对应的解决办法:

1. 空间要素的坐标系不统一

这是最容易踩的坑——如果你的国道线(mapa)、警察局(postos)和事故点(tab_sf)使用的是不同的坐标系,ggplot2在分面时尝试对齐图层,可能会错误转换坐标,导致出现纬度<-90的异常值。

解决办法:
用sf包的st_transform()把所有空间对象转成同一个坐标系,巴伊亚州常用的是SIRGAS 2000 UTM 23S(EPSG:31983):

library(sf)
# 统一转换坐标系
mapa <- st_transform(mapa, crs = 31983)
postos <- st_transform(postos, crs = 31983)
tab_sf <- st_transform(tab_sf, crs = 31983)

2. 年份变量的类型错误

如果tab_sf中的年份字段是字符型(比如"2017"、"2018"),而不是因子型,facet操作在分组时可能会隐性触发数据筛选或图层错位,虽然表面上没改数据,但会导致空组或异常图层的坐标计算错误。

解决办法:
把年份字段转成因子型:

tab_sf$ano <- as.factor(tab_sf$ano)
# 然后分面时用~ano
ggplot() +
  geom_sf(data = mapa) +
  geom_sf(data = tab_sf, aes(color = tipo_acidente)) +
  facet_wrap(~ano)

3. Shiny动态渲染中的reactive对象问题

如果你的tab_sf是通过reactive表达式生成的(比如根据用户输入筛选数据),可能在分面时出现以下问题:

  • reactive表达式不小心把sf对象转换成了普通dataframe(比如用dplyr操作时丢失了空间属性)
  • 动态筛选后返回了空的空间对象,导致渲染时坐标计算出错

解决办法:

  • 在reactive表达式末尾用st_as_sf()确保返回的是sf对象:
filtered_tab_sf <- reactive({
  tab_sf %>%
    filter(ano == input$selected_year) %>%
    st_as_sf() # 强制保留空间属性
})
  • 在renderPlot中添加检查,确保数据非空后再渲染:
output$accident_plot <- renderPlot({
  req(filtered_tab_sf()) # 确保数据存在
  ggplot() +
    geom_sf(data = mapa) +
    geom_sf(data = filtered_tab_sf()) +
    facet_wrap(~ano)
})

4. ggplot2或sf包的版本兼容性问题

早期版本的ggplot2对geom_sf的分面支持有bug,可能导致坐标矩阵计算错误。

解决办法:
更新到最新版本的包:

install.packages(c("ggplot2", "sf"))

快速排查步骤

如果还是找不到问题,可以先做以下测试:

  • 在Shiny中输出tab_sf的空间范围:st_bbox(tab_sf),分面前后对比,确认坐标系没有被意外修改
  • 单独绘制某一年的事故数据(不使用分面),看是否正常,排除单年份数据的异常

内容的提问来源于stack exchange,提问作者danilo ribeiro de abreu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:09:21