第四章 重点解析
SECTION01 / 05
1.0空间数据导论
Introduction to Spatial Data
空间数据的两种形态
Vector Features & Raster Cells
气温
一格记录一个气温值
2024 年 7 月每日最高 2 米气温的月平均值,单位为 °C。海域无数据;细节包含空间下尺度估计。
读图时先核对时间、单位与色阶。
一格记录夜间光信号
亮度在空间上逐格变化;明亮区域反映较强夜间光信号,不能直接当作人口或经济总量。
读图时留意无光区域、水体与云光校正。
NASA GIBS · VIIRS Black Marble · 2016一格记录一个地类
像元保存土地覆盖类别代码。颜色用于区分类别,不表示数值高低。
- 常绿针叶林
- 常绿阔叶林
- 落叶针叶林
- 落叶阔叶林
- 混交林
- 密灌木地
- 疏灌木地
- 木本稀树草原
- 稀树草原
- 草地
- 常年湿地
- 耕地
- 城市与建设用地
- 耕地/自然植被
- 常年积雪与冰川
- 荒地/裸地
- 水体
- 未分类
空间点数据
Spatial Point Data
点击空白处添加点;点击已有点选中。方向键移动准星,按 Enter 放置。这里是 x 从 0 到 100、y 从 0 到 45 的教学坐标,不是真实经纬度。
点要素表
| ID | 属性 | 坐标对(x, y) |
|---|
—空间线数据
Spatial Line Data
依次放置顶点;至少两点后点“完成线路”,或按 Shift+Enter。这里是 x 从 0 到 100、y 从 0 到 45 的教学坐标,不是真实经纬度。
线要素表
| ID | 属性 | 顶点概览 |
|---|
—空间面数据
Spatial Polygon Data
依次放置至少 3 个不同顶点,再点“闭合并保存”或按 Shift+Enter。方向键移动准星,按 Enter 放置。这里是 x 从 0 到 100、y 从 0 到 45 的教学坐标,不是真实经纬度。
面要素表
| ID | 属性 | 闭合顺序 |
|---|
—sf:一个图层,一张要素表
One Layer, One Feature Table
三个独立的 sf 图层
一行一个要素,一列一个变量
点击表格行查看坐标坐标参考系:位置与投影
Coordinate Reference Systems
地理坐标系
WGS 84
EPSG:4326
WGS 84 用经纬度定位。图中把角度直接画成平面,高纬地区仍被拉宽;图面长度不能直接当作米。
常见的地理坐标系
以下坐标都以角度表达位置;EPSG 编码也可在 R 中用于 st_crs()。
- 全球常见WGS 84
EPSG:4326经纬度 · 度 - 中国CGCS2000
EPSG:4490经纬度 · 度 - 英国OSGB36
EPSG:4277经纬度 · 度 - 美国NAD83
EPSG:4269经纬度 · 度 - 法国RGF93 v1
EPSG:4171经纬度 · 度
名称相近也可能采用不同基准或版本;先检查原数据的 CRS。
Web Mercator 与 Equal Earth 是不同投影方法;本页的 EPSG:3857 与 EPSG:8857 是两个具体的投影坐标系。同一点 P:EPSG:3857 为 x = 3,339,585 m,y = 2,875,745 m;EPSG:8857 为 x = 2,745,482 m,y = 3,160,342 m。
图面比值据本页 Natural Earth 轮廓计算。经纬度直绘和 Equal Earth 可显示完整极区;Web Mercator 在约 ±85.05° 截止,无法呈现极点。联合国大会 A/RES/80/307(2026)鼓励面积比较使用等面积投影,未禁用墨卡托。球面:高纬纬线较短
越靠近两极,同一圈纬线越短。
墨卡托:高纬被拉开
横向、纵向都拉伸;高纬陆地在图上显得更大。
Equal Earth:保留面积比例
调整纬线宽度与间距;面积比例保留,形状有取舍。
五个地区的投影坐标系
- 英国 · 大不列颠British National Grid
EPSG:27700单位:米(m) - 中国 · 上海中心城区所在区带CGCS2000 高斯–克吕格
EPSG:4549单位:米(m) - 法国本土Lambert-93
EPSG:2154单位:米(m) - 美国 · 纽约市及长岛NAD83 / New York Long Island
EPSG:32118单位:米(m) - 日本 · 京都JGD2024 平面直角 VI
EPSG:6674单位:米(m)
SECTION02 / 05
2.0空间数据读写
Reading and Writing Spatial Data
空间数据存储方式
How Spatial Data Are Stored
北卡罗来纳县界 Shapefile
100 个县级面 · EPSG:4267
同一目录中的配套文件
nc.shp几何形状nc.shx几何索引nc.dbf属性表nc.prj坐标系定义实际路径:sf/shape/nc.* · 四个文件同名并位于同一目录
读入 sf
shp_path <- system.file("shape/nc.shp", package = "sf")
nc_sf <- st_read(shp_path, quiet = TRUE)读取时指定 .shp;复制或分享数据时一并保留配套文件。.prj 提供 CRS 定义。
同一县界的单文件版本 GeoPackage
100 个县级面 · EPSG:4267
文件与实际图层
gpkg/nc.gpkgnc.gpkg100 个面要素GeoPackage 可存多个图层;这个样本经 st_layers() 核对,只有 1 个图层。
先查看,再读入
gpkg_path <- system.file("gpkg/nc.gpkg", package = "sf")
st_layers(gpkg_path)
nc_sf <- st_read(gpkg_path,
layer = "nc.gpkg", quiet = TRUE)layer 使用实际图层名,不能把示意名称直接写进代码。
伦敦共享单车站点 GeoJSON
532 个点 · sf 读入后 EPSG:4326
首个 Feature 的实际字段
Feature / Point"108539"[-0.093387797474861, 51.529125213623047]顶层为 FeatureCollection · 原文声明 CRS84 · spData/shapes/cycle_hire_osm.geojson
读入 sf
geojson_path <- system.file(
"shapes/cycle_hire_osm.geojson", package = "spData")
cycle_sf <- st_read(geojson_path, quiet = TRUE)文件保存要素属性和点坐标;普通 .json 文件未必符合 GeoJSON 结构。
伦敦共享单车站点 CSV + 坐标列
12 条记录 · 5 个字段
CSV 原文节选
osm_id,name,capacity,lon,lat
108539,Windsor Terrace,14,-0.09338779747486115,51.52912521362305lon → X / 经度lat → Y / 纬度实际文件:media/cycle_hire_osm_excerpt.csv · 与上面的 GeoJSON 来自不同历史快照
由坐标列生成 sf
cycle_tbl <- read_csv("cycle_hire_osm_excerpt.csv",
col_types = cols(osm_id = col_character()))
cycle_sf <- st_as_sf(cycle_tbl,
coords = c("lon", "lat"), crs = 4326)CSV 本身不保存 CRS;这里的 EPSG:4326 已根据来源对象核对。运行代码时须先取得该 CSV 文件。
三种格式读入,GeoJSON 写出
Read with sf · Export as GeoJSON
选择一种输入格式
读入 sf → 写出新 GeoJSON
# 01 · 读入 Shapefile
shp_path <- system.file("shape/nc.shp", package = "sf")
nc_sf <- shp_path %>% st_read(quiet = TRUE)
# 02 · 转为 WGS 84,写出 GeoJSON
out_geojson <- tempfile(fileext = ".geojson")
nc_sf %>%
st_transform(4326) %>%
st_write(
dsn = out_geojson, driver = "GeoJSON",
layer_options = "RFC7946=YES", quiet = TRUE)
# 03 · 重读并核对
nc_out <- out_geojson %>% st_read(quiet = TRUE)
c(rows = nrow(nc_out), epsg = st_crs(nc_out)$epsg)
# 01 · 查看图层,读入 GeoPackage
gpkg_path <- system.file("gpkg/nc.gpkg", package = "sf")
gpkg_path %>% st_layers()
nc_gpkg_sf <- gpkg_path %>% st_read(layer = "nc.gpkg", quiet = TRUE)
# 02 · 转为 WGS 84,写出 GeoJSON
out_geojson <- tempfile(fileext = ".geojson")
nc_gpkg_sf %>%
st_transform(4326) %>%
st_write(
dsn = out_geojson, driver = "GeoJSON",
layer_options = "RFC7946=YES", quiet = TRUE)
# 03 · 重读并核对
nc_out <- out_geojson %>% st_read(quiet = TRUE)
c(rows = nrow(nc_out), epsg = st_crs(nc_out)$epsg)
# 01 · 读入 GeoJSON
geojson_path <- system.file(
"shapes/cycle_hire_osm.geojson", package = "spData")
cycle_sf <- geojson_path %>%
st_read(quiet = TRUE)
# 02 · 另存为新的 GeoJSON 文件
out_geojson <- tempfile(fileext = ".geojson")
cycle_sf %>%
st_write(
dsn = out_geojson, driver = "GeoJSON",
layer_options = "RFC7946=YES", quiet = TRUE)
# 03 · 重读并核对
cycle_out <- out_geojson %>% st_read(quiet = TRUE)
c(rows = nrow(cycle_out), epsg = st_crs(cycle_out)$epsg)
从 CSV 坐标表到 sf
From a CSV Table to Spatial Features
cycle_tbl
# A tibble: 12 × 5| osm_id <chr> | name <chr> | capacity <dbl> | lon <dbl> | lat <dbl> |
|---|
识别属性与坐标列
CSV 中 lon / lat 是位置数值列;生成 sf 后才有 geometry。
X / lon −0.093388° · Y / lat 51.529125°
cycle_sf
# sf: 12 × 4 · POINT · EPSG:4326| osm_id <chr> | name <chr> | capacity <dbl> | geometry <POINT> |
|---|
生成点时发生了什么?
coordslon → X,lat → Y列的顺序决定坐标顺序。
crs4326 · WGS 84依据已核对的源对象声明 CRS;此步没有转换坐标。
remove默认 TRUE · 不保留原列lon / lat 合成 geometry 后,不再作为属性列显示。
转换前:经纬度
st_transform(27700)转换后:平面坐标
读取 CSV 数据
cycle_tbl <- read_csv("cycle_hire_osm_excerpt.csv",
col_types = cols(osm_id = col_character()))cycle_sf <- cycle_tbl %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326)cycle_bng <- cycle_sf %>% st_transform(27700)把指标接到边界上
Join a Data Table to Spatial Boundaries
边界 boundary_sf
| geo_id | 名称 | geometry |
|---|---|---|
| A 区 | POLYGON | |
| B 区 | POLYGON | |
| C 区 | POLYGON |
指标 attr_tbl
| geo_id | 指标值 |
|---|---|
"01" | 8.4 |
"03" | 13.1 |
结果 joined_sf示意数据
点击上方代码,查看连接结果
| geo_id | 名称 | 指标值 | geometry |
|---|---|---|---|
"01" | A 区 | 8.4 | POLYGON |
"02" | B 区 | NA | POLYGON |
"03" | C 区 | 13.1 | POLYGON |
SECTION03 / 05
3.0空间数据处理
Spatial Data Processing
从属性处理到空间处理
From Attributes to Spatial Relationships
同一份 sf 数据
一行一个地理要素
| geo_id | 名称 | 人口 | geometry |
|---|---|---|---|
| 01 | A 区 | 2.4 万 | POLYGON |
| 02 | B 区 | 1.8 万 | POLYGON |
| 03 | C 区 | 3.1 万 | POLYGON |
sf:带 geometry 列的 data.framefilter() 筛选要素 · mutate() 新增属性
让位置参与处理
由 geometry 判断要素之间的空间关系
点落在哪个区域内?
st_within()
按位置匹配,再把区域属性接给点
st_join()
按设定距离生成缓冲范围
st_buffer()
空间关系:按位置找到匹配
Spatial predicates · Which features match?
边界上的 Q 与内部的 P,判断结果不同。
空间连接与叠置
Spatial Join & Overlay
点落入街区,获得街区属性
站点落在哪个街区?
points_sfregions_sfP1位于 A 区 · 居住区 · 人口 24,000连接前核对两图层 CRS
街区属性写入站点表
| 点原有 | 从面带入的属性 | 点几何 | ||
|---|---|---|---|---|
| point_id | region_id | area_type | population | geometry |
| P1 | A | 居住区 | 24000 | POINT |
| P2 | A | 居住区 | 24000 | POINT |
| P3 | B | 商业区 | 18000 | POINT |
| P4 | B | 商业区 | 18000 | POINT |
| P5 | NA | NA | NA | POINT |
点击代码,查看面的属性如何进入点表。
A、B 各覆盖哪些分区?
target_sf来源区source_sfA总面积 10 km²;交叠 4 / 4 / 2 km² → 36%等积 CRS 测面积
按交叠面积计算街区绿地率
| 目标面 | 面积加权 | 目标面几何 |
|---|---|---|
| target_id | green_rate | geometry |
| A | 36% | POLYGON |
| B | 60% | POLYGON |
假设来源区内绿地率均匀;按交叠面积加权。
缓冲区分析:从点生成面
Buffer Analysis · From Point to Polygon
两座站点,同一缓冲半径
AWaterloo BEmbankment 交叠
st_drop_geometry():只留下属性
Remove Geometry · Keep the Attributes
points_joined
| point_id | region_id | area_type | population | geometry |
|---|---|---|---|---|
| P1 | A | 居住区 | 24000 | POINT |
| P2 | A | 居住区 | 24000 | POINT |
| P3 | B | 商业区 | 18000 | POINT |
| P4 | B | 商业区 | 18000 | POINT |
| P5 | NA | NA | NA | POINT |
保留属性
只移除 geometry;原 sf 不变
point_tbl
| point_id | region_id | area_type | population |
|---|---|---|---|
| P1 | A | 居住区 | 24000 |
| P2 | A | 居住区 | 24000 |
| P3 | B | 商业区 | 18000 |
| P4 | B | 商业区 | 18000 |
| P5 | NA | NA | NA |
运行中间的函数,观察哪一列消失。
去掉几何后,继续处理属性
先运行 st_drop_geometry(),再选择一种属性运算。
selected_points <- point_tbl %>%
filter(population >= 20000)selected_points · 2 行| point_id | region_id | area_type | population |
|---|---|---|---|
| P1 | A | 居住区 | 24000 |
| P2 | A | 居住区 | 24000 |
filter() 也可直接筛选 sf,并保留几何;这里先去几何,是为了得到纯属性表。
point_counts <- point_tbl %>%
filter(!is.na(region_id)) %>%
group_by(region_id) %>%
summarise(n_points = n(), .groups = "drop")point_counts · 2 行| region_id | n_points |
|---|---|
| A | 2 |
| B | 2 |
直接汇总 sf 会合并组内几何;先去几何只生成属性统计。P5 在计数前排除。
SECTION04 / 05
4.0空间数据可视化
Visualizing Spatial Data
ggplot + sf:用 geom_sf() 绘图
The Same Grammar · A Spatial Geometry Layer
county_map.R
class_43_countiesclass_43_counties %>%
ggplot()
class_43_counties %>%
ggplot() +
geom_sf()
class_43_counties %>%
ggplot() +
geom_sf(fill = "#E8D7BD",
colour = "#8B6557",
linewidth = 0.15) +
labs(title = "US counties · 2025") +
theme_minimal()
ggplot() 接收 sf 数据;此时尚无几何图层。
美国本土县级边界
class_43_counties %>% ggplot()画布已建立,尚未加入绘图图层。
同一数据,三种分级断点
Classification Methods · Same Data, Different Breaks
log10(1 + 密度) → 五级分色寻找组内差异较小的分组
557 · 894 · 931 · 514 · 212
每级县级单元数尽量接近
622 · 621 · 622 · 621 · 622
在对数尺度划分等宽区间
808 · 1,626 · 548 · 117 · 9
三种分级方法的地图对比
Three Classification Methods · One County Map
美国县级人口密度 · 2025
classInt::classIntervals(
..., style = "fisher"
)
- 0.03–3.9557
- 3.9–15.7894
- 15.7–54.4931
- 54.4–269.6514
- 269.6–28,370212
分级变量:log10(1 + 人口密度)
SECTION05 / 05
5.0空间制图要求与美化
Cartographic Standards and Design
中国地图:先过三道检查
Basemap Source · Map Content · Intended Use
底图有来源
优先在自然资源部标准地图服务系统选择适合图幅的底图。
内容按图幅核对
中国全图应表达完整范围,并核对图幅和比例尺下应表示的重要岛屿。
按用途核对
课堂练习、直接使用标准图、公开新增专题图,分别记录来源与要求。
用 R 制作中国专题地图
A County-Level Choropleth with a South China Sea Inset
Albers 等面积投影
四种设色方案的地图效果
Categorical · Diverging · Continuous · Classified
双变量专题地图
A + B → C · Bivariate Choropleth
人口密度
按县级数值分为四档
人口变化率
同一批县级单元,另分四档
一格颜色
读取两个等级
密度分位 ↑
变化率分位 →
Thanks
第五周:第四章 重点解析