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

ggplot绘制MENA地区地图时filter筛选国家标签报错求助

问题描述

我尝试创建中东和北非(MENA)地区的地图并标注国家名称,通过经纬度坐标划定地图范围后,生成的地图包含部分非MENA国家。因此我想用filter函数结合国家名称向量,仅为目标区域内的国家标注名称,但添加filter后出现错误:

Error in data.matrix(data) : 'list' object cannot be coerced to type 'double'

未添加filter时可正常运行的代码:

ggplot(data = world) +
  geom_sf(fill= "antiquewhite") +
  geom_text(data = world_points , aes(x=X, y=Y, label=name),
            color = "darkblue", fontface = "bold", check_overlap = TRUE) +
  annotate(geom = "text", x = 20, y = 35, label = "MØNA", 
           fontface = "italic", color = "grey22", size = 6) +
  coord_sf(xlim = c(-18.0, 72.0), ylim = c(11.5, 45.0), expand = FALSE) +
  xlab("经度") + ylab("纬度") +
  ggtitle("中东和北非地区") +
  theme(panel.background = element_rect(fill = "aliceblue"))

添加filter后报错的代码:

ggplot(data = world) +
  geom_sf(fill = "antiquewhite") +
  coord_sf(xlim = c(-18.0, 72.0), ylim = c(11.5, 45.0), expand = FALSE) +
  geom_text(data = world_points %>% 
              filter(name %in% c('Egypt', 'Tunisia', 'Algeria', 'Libya', 
                                 'Morocco', 'Sudan', 'Jordan', 'Israel', 
                                 'Palestine', 'Syria', 'Iraq', 'Turkey',
                                 'Iran', 'Afghanistan', 'Saudi Arabia', 'Kuwait', 
                                 'United Arab Emirates', 'Qatar', 'Oman', 'Yemen', 'Bahrain',
                                  'Lebanon')), aes(x=X, y=Y, label=name),
              color = "darkblue", size = 3, check_overlap = FALSE) +
  annotate(geom = "text", x = 20, y = 35, label = "MØNA", 
           fontface = "italic", color = "grey22", size = 6) +
  
  xlab("经度") + ylab("纬度") +
  ggtitle("中东和北非地区") +
  theme(panel.background = element_rect(fill = "aliceblue"))

解决方案

错误原因

world_points是sf空间对象,包含一个geometry列(数据类型为list)。使用filter后该列依然存在,而geom_text在处理数据时会尝试将整个数据集转换为数值矩阵,遇到list类型的geometry列就会触发报错。

解决方法1:转换为普通数据框

在filter后将sf对象转换为普通数据框,只保留需要的X、Y和name列:

ggplot(data = world) +
  geom_sf(fill = "antiquewhite") +
  coord_sf(xlim = c(-18.0, 72.0), ylim = c(11.5, 45.0), expand = FALSE) +
  geom_text(
    data = world_points %>% 
      filter(name %in% c('Egypt', 'Tunisia', 'Algeria', 'Libya', 
                         'Morocco', 'Sudan', 'Jordan', 'Israel', 
                         'Palestine', 'Syria', 'Iraq', 'Turkey',
                         'Iran', 'Afghanistan', 'Saudi Arabia', 'Kuwait', 
                         'United Arab Emirates', 'Qatar', 'Oman', 'Yemen', 'Bahrain',
                          'Lebanon')) %>%
      as.data.frame() %>%  # 转换为普通数据框
      select(X, Y, name),  # 只保留需要的列
    aes(x=X, y=Y, label=name),
    color = "darkblue", size = 3, check_overlap = FALSE
  ) +
  annotate(geom = "text", x = 20, y = 35, label = "MØNA", 
           fontface = "italic", color = "grey22", size = 6) +
  xlab("经度") + ylab("纬度") +
  ggtitle("中东和北非地区") +
  theme(panel.background = element_rect(fill = "aliceblue"))

解决方法2:使用geom_sf_text

如果world_points是包含国家几何中心的sf对象,直接用geom_sf_text可以避免手动处理坐标列,它会自动读取sf对象的geometry列:

ggplot(data = world) +
  geom_sf(fill = "antiquewhite") +
  coord_sf(xlim = c(-18.0, 72.0), ylim = c(11.5, 45.0), expand = FALSE) +
  geom_sf_text(
    data = world_points %>% 
      filter(name %in% c('Egypt', 'Tunisia', 'Algeria', 'Libya', 
                         'Morocco', 'Sudan', 'Jordan', 'Israel', 
                         'Palestine', 'Syria', 'Iraq', 'Turkey',
                         'Iran', 'Afghanistan', 'Saudi Arabia', 'Kuwait', 
                         'United Arab Emirates', 'Qatar', 'Oman', 'Yemen', 'Bahrain',
                          'Lebanon')),
    aes(label=name),
    color = "darkblue", size = 3, check_overlap = FALSE
  ) +
  annotate(geom = "text", x = 20, y = 35, label = "MØNA", 
           fontface = "italic", color = "grey22", size = 6) +
  xlab("经度") + ylab("纬度") +
  ggtitle("中东和北非地区") +
  theme(panel.background = element_rect(fill = "aliceblue"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:00:35