R 语言空间地图实战:从城市热力图到地理分布图,一篇吃透

R 语言空间地图实战:从城市热力图到地理分布图,一篇吃透

地图可视化从来不只是画几条线、填几种颜色那么简单。当你面对一份城市人口数据,或者一长串省份的经济指标时,如何让这些冰冷的数字在空间维度上"活"起来?R 语言的空间生态,正是为此而生。

本文不是入门指南,而是面向实战的完整方案------城市热力图、地理分布图、专业出版级地图,代码可直接复用。


一、搭建工作环境:核心工具链

先把"画板"和"颜料"准备好。打开 RStudio 控制台,一键安装:

less 复制代码
r
install.packages(c("sf", "ggplot2", "rnaturalearth", "rnaturalearthdata",
                   "dplyr", "viridis", "leaflet", "leaflet.extras",
                   "tmap", "ggspatial"))

各包分工明确:

角色
sf 现代空间数据处理基石,统一管理矢量几何与属性
ggplot2 可视化语法核心,与 sf 无缝集成
rnaturalearth 高质量全球地图数据,免去四处找底图的苦
leaflet 交互式热力图,网页端探索利器
tmap 几行代码画出出版级区域热图
ggspatial 比例尺、指北针等专业元素一键添加

加载:

scss 复制代码
r
library(sf)
library(ggplot2)
library(rnaturalearth)
library(dplyr)
library(viridis)
library(leaflet)
library(leaflet.extras)
library(tmap)
library(ggspatial)

⚠️ 关键习惯:项目开始时统一坐标参考系统(CRS)。全球可视化用 WGS84(EPSG:4326);中国区域分析建议用等面积投影如 Albers。


二、实战一:城市热力图(ggplot2 + 地理底图)

2.1 经纬度散点热力图

假设有一份城市数据,包含经纬度和某项指标(如人口):

ini 复制代码
r
# 模拟数据
set.seed(123)
city_data <- data.frame(
  city = c("北京", "上海", "广州", "深圳", "成都", "杭州", "武汉", "西安"),
  lon = c(116.407, 121.473, 113.264, 114.057, 104.066, 120.153, 114.305, 108.940),
  lat = c(39.904, 31.230, 23.129, 22.543, 30.572, 30.287, 30.593, 34.341),
  population = c(2189, 2487, 1868, 1756, 2094, 1220, 1365, 1295)  # 万人
)

# 转换为 sf 对象
city_sf <- st_as_sf(city_data, coords = c("lon", "lat"), crs = 4326)

# 加载中国底图
china <- ne_countries(scale = "medium", country = "China", returnclass = "sf")

# 绘图
ggplot() +
  geom_sf(data = china, fill = "grey95", color = "grey70") +
  geom_sf(data = city_sf, aes(size = population, color = population), alpha = 0.8) +
  scale_size_continuous(range = c(3, 12), name = "人口(万人)") +
  scale_color_viridis(option = "plasma", name = "人口(万人)") +
  theme_minimal() +
  labs(title = "中国主要城市人口热力图", x = "经度", y = "纬度")

点的大小和颜色双重编码人口规模,一目了然。

2.2 密度热力图层(ggmap 方案)

如果想要更"热"的效果------连续的热力渐变:

ini 复制代码
r
library(ggmap)

# 获取底图
base_map <- get_map(location = c(lon = 110, lat = 35), zoom = 5, maptype = "terrain")

ggmap(base_map) +
  geom_point(data = city_data, aes(x = lon, y = lat, size = population, color = population),
             alpha = 0.7) +
  scale_color_gradient(low = "blue", high = "red") +
  scale_size_continuous(range = c(2, 10)) +
  labs(title = "城市人口密度热力图") +
  theme_void()

三、实战二:交互式地图热力图(leaflet)

静态图不够过瘾?leaflet 让你在浏览器里缩放、悬停查看数值:

ini 复制代码
r
library(leaflet)
library(leaflet.extras)

leaflet(city_data) %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~lon, lat = ~lat,
    radius = ~population / 80,          # 半径映射人口
    color = ~viridis::viridis(100)[cut(population, breaks = 100)],
    fillOpacity = 0.7,
    popup = ~paste0("<b>", city, "</b><br>人口: ", population, "万人")
  ) %>%
  addLegend("bottomright",
            pal = colorNumeric(viridis(100), domain = city_data$population),
            values = ~population,
            title = "人口(万人)")

真正的热力图(连续密度,非散点):

ini 复制代码
r
leaflet() %>%
  addTiles() %>%
  addHeatmap(
    data = city_data,
    lng = ~lon, lat = ~lat,
    intensity = ~population,
    radius = 15, blur = 20, max = 0.5,
    gradient = c("blue", "cyan", "lime", "red")
  )

radius 控制热斑半径,blur 控制模糊程度,max 控制强度上限------三个参数调好,效果立现。


四、实战三:区域数据热力图(tmap,几行搞定)

这是最省力的方案,尤其适合省级/市级 GDP、PM2.5 等面数据。

ini 复制代码
r
library(tmap)

# 模拟省级数据
province_data <- data.frame(
  name = c("广东", "江苏", "山东", "浙江", "河南", "四川"),
  GDP = c(135673, 128222, 92069, 77715, 61345, 56749)  # 亿元
)

# 读取中国省级边界(需提前准备 GeoJSON 或 Shapefile)
# china_provinces <- st_read("china_provinces.geojson")

# 这里用 rnaturalearth 的中国边界做演示
china_provinces <- ne_states(country = "China", returnclass = "sf")

# 合并数据
map_data <- left_join(china_provinces, province_data, by = c("name" = "name"))

# 彩色热图
tm_shape(map_data) +
  tm_polygons("GDP", title = "GDP(亿元)", palette = "YlOrRd") +
  tm_layout(title = "2023年中国部分省份GDP分布", legend.outside = TRUE)

# 灰度热图(适合印刷)
tm_shape(map_data) +
  tm_polygons("GDP", title = "GDP(亿元)", palette = "Greys") +
  tm_layout(title = "2023年中国部分省份GDP分布(灰度版)")

tm_style("bw") 是灰度风格,tm_style("beaver") 是另一种配色------换一行代码,风格即变。


五、实战四:出版级专业地图(ggplot2 + ggspatial)

学术论文需要比例尺、指北针?ggspatial 一键搞定:

ini 复制代码
r
library(ggspatial)

ggplot() +
  geom_sf(data = china_provinces, fill = "white", color = "grey60", size = 0.3) +
  geom_sf(data = map_data, aes(fill = GDP), color = "grey40") +
  scale_fill_viridis(option = "plasma", name = "GDP(亿元)") +
  annotation_scale(location = "bl", width_hint = 0.4) +     # 比例尺
  annotation_north_arrow(location = "tl", style = north_arrow_fancy_orienteering) +  # 指北针
  theme_minimal() +
  labs(title = "中国省级GDP分布", x = "经度", y = "纬度")

这张图直接丢进论文,审稿人挑不出毛病。


六、避坑清单:实战中最容易翻车的点

解决方案
国家名称对不上 数据里是 "United States",地图里是 "United States of America"------用 name_mapping 手动映射,或 rwcvp_match_names() 自动匹配
CRS 不统一导致地图扭曲 开工第一件事:st_crs(your_data) <- 4326,所有数据统一 WGS84
点太多导致图形卡顿 geom_hex()stat_summary_2d() 做密度聚合,别硬画几万个点
中文乱码 读 CSV 时加 fileEncoding = "GBK",或统一转 UTF-8
图例太丑 viridis 配色对色盲友好,RColorBrewerYlOrRd 是经典热力图色系

速查:该用哪个方案?

需求 推荐方案 核心函数
城市散点热力图 ggplot2 + sf geom_sf()
连续密度热力图 leaflet addHeatmap()
省级/区域面数据热图 tmap tm_polygons()
学术出版级地图 ggplot2 + ggspatial annotation_scale()
物种/植物全球分布 rwcvp wcvp_distribution_map()

代码全在这里了。从几行代码的城市热力图,到带比例尺指北针的出版级地图,R 的空间可视化能力远比你想象的强大。挑一个场景,复制粘贴,跑起来。

相关推荐
二月龙1 小时前
Shiny 对接 Excel / 数据库:从文件上传到自动分析
后端
JavaGuide1 小时前
Token 暴降 59%!这个项目让 Claude Code / Codex 不再满仓库乱翻。
后端·ai编程
Oneslide2 小时前
Vmware WorkStation Pro 下载和使用指南
后端
神奇小汤圆2 小时前
SwiftClockCache:一个高性能并发缓存的设计与实现
后端
神奇小汤圆2 小时前
学完 Spring Boot 再看 FastAPI,我破防了
后端
用户987409238873 小时前
deepspeed zero3 + llamafactory 保存checkpoint后第一step 就 OOM
后端
长大19883 小时前
ggplot2 高阶美化:SCI 期刊级论文图表从零绘制全流程
后端
墩墩大魔王丶3 小时前
macOS Rust 安装教程:自定义 CARGO_HOME 和 RUSTUP_HOME
后端
进阶的小名4 小时前
Spring Boot SSE + Nginx 配置:解决 EventSource 不实时返回、连接超时、流式响应被缓冲问题
spring boot·后端·nginx