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

数据框经纬度投影至Mollweide时全部点聚集于原点的问题排查

解决Mollweide投影下数据点聚集于原点的问题

问题概况

  • 需求:将古颚类(Palaeognathae)的occurrence数据坐标转换到Mollweide投影下绘图
  • 现象:
    • 单独绘制无数据点的Mollweide投影地图显示正常
    • 未设置投影时,数据点能正常显示在对应地理位置
    • 添加数据后,所有点聚集在地图原点(0,0)附近
  • 尝试过的操作:使用coord_sf(crs = "+proj=moll")但未解决问题

核心原因

地图与数据的坐标参考系统(CRS)不匹配:

  • 若提前用st_transform将地图转换为Mollweide投影,地图的坐标已变为该投影下的平面坐标
  • 但原始数据还是普通数据框中的WGS84经纬度(EPSG:4326),直接用geom_point添加时,ggplot会把经纬度值当成Mollweide投影的坐标值,由于两种坐标的范围完全不同,所有点会被错误映射到原点附近

解决方案

方法一:将数据转换为sf对象并统一投影

把原始数据框转为sf空间对象,先设置正确的原始CRS,再转换到Mollweide投影,最后用geom_sf绘制点:

library(tidyverse)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
library(ggthemes)

# 加载地图数据
world <- ne_countries(scale = "medium", returnclass = "sf")

# 加载并处理古颚类数据
ratites <- read_csv("Palaeognathae_Occurance_dataRevised.csv")  # 替换为你的数据文件路径
Ratite_C <- ratites %>%
  select(accepted_name, Longitude, latitude, early_interval, cc) %>%
  # 转换为sf对象,设置原始CRS为WGS84
  st_as_sf(coords = c("Longitude", "latitude"), crs = 4326) %>%
  # 统一转换到Mollweide投影
  st_transform(crs = "+proj=moll")

# 按时间区间拆分数据
Cret <- Ratite_C %>% filter(early_interval == "Cretaceous")
Paleo <- Ratite_C %>% filter(early_interval == "Paleocene")
Eoc <- Ratite_C %>% filter(early_interval == "Eocene")
Oligo <- Ratite_C %>% filter(early_interval == "Oligocene")
Mioc <- Ratite_C %>% filter(early_interval == "Miocene")
Plio <- Ratite_C %>% filter(early_interval == "Pliocene")
Pleis.Holo <- Ratite_C %>% filter(early_interval %in% c("Pleistocene", "Holocene"))

# 转换地图到Mollweide投影
world_moll <- world %>% st_transform(crs = "+proj=moll")

# 绘图
R.Smap <- ggplot() +
  geom_sf(data = world_moll, color = "black", fill = "white") +
  geom_sf(data = Cret, size = 3, shape = 23, fill = "orange") +
  geom_sf(data = Paleo, size = 3, shape = 21, fill = "lightblue") +
  geom_sf(data = Eoc, size = 3, shape = 21, fill = "goldenrod4") +
  geom_sf(data = Oligo, size = 3, shape = 21, fill = "yellow") +
  geom_sf(data = Mioc, size = 3, shape = 21, fill = "purple") +
  geom_sf(data = Plio, size = 3, shape = 21, fill = "green") +
  geom_sf(data = Pleis.Holo, size = 2, shape = 21, fill = "cyan") +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_rect(fill = 'azure2'))

R.Smap

方法二:用coord_sf统一设置全局投影(更简便)

无需提前转换地图和数据的CRS,直接在ggplot中用coord_sf指定目标投影,ggplot会自动完成所有图层的投影转换:

library(tidyverse)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
library(ggthemes)

# 加载地图数据
world <- ne_countries(scale = "medium", returnclass = "sf")

# 加载并处理古颚类数据
ratites <- read_csv("Palaeognathae_Occurance_dataRevised.csv")  # 替换为你的数据文件路径
Ratite_C <- ratites %>%
  select(accepted_name, Longitude, latitude, early_interval, cc)

# 按时间区间拆分数据
Cret <- Ratite_C %>% filter(early_interval == "Cretaceous")
Paleo <- Ratite_C %>% filter(early_interval == "Paleocene")
Eoc <- Ratite_C %>% filter(early_interval == "Eocene")
Oligo <- Ratite_C %>% filter(early_interval == "Oligocene")
Mioc <- Ratite_C %>% filter(early_interval == "Miocene")
Plio <- Ratite_C %>% filter(early_interval == "Pliocene")
Pleis.Holo <- Ratite_C %>% filter(early_interval %in% c("Pleistocene", "Holocene"))

# 绘图,通过coord_sf统一设置Mollweide投影
R.Smap <- ggplot() +
  geom_sf(data = world, color = "black", fill = "white") +
  geom_point(data = Cret, aes(x = Longitude, y = latitude), size = 3, shape = 23, fill = "orange") +
  geom_point(data = Paleo, aes(x = Longitude, y = latitude), size = 3, shape = 21, fill = "lightblue") +
  geom_point(data = Eoc, aes(x = Longitude, y = latitude), size = 3, shape = 21, fill = "goldenrod4") +
  geom_point(data = Oligo, aes(x = Longitude, y = latitude), size = 3, shape = 21, fill = "yellow") +
  geom_point(data = Mioc, aes(x = Longitude, y = latitude), size = 3, shape = 21, fill = "purple") +
  geom_point(data = Plio, aes(x = Longitude, y = latitude), size = 3, shape = 21, fill = "green") +
  geom_point(data = Pleis.Holo, aes(x = Longitude, y = latitude), size = 2, shape = 21, fill = "cyan") +
  coord_sf(crs = "+proj=moll") +  # 关键:统一设置投影
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_rect(fill = 'azure2'))

R.Smap

注意事项

  • 避免使用attach()函数,容易引发变量冲突,优先使用dplyr管道或直接引用数据框
  • 确认数据中的Longitude和latitude是标准WGS84经纬度(经度范围-180180,纬度范围-9090)
  • 方法二更适合快速绘图,无需手动转换每个数据集的CRS

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:05:24