如何在R中按人口密度归一化空间热力图以分析口音地理分布?
在R中实现人口密度归一化的口音地理分布热力图方法
核心思路
要避免大城市样本过多导致的偏差,核心是将口音样本点的密度除以对应区域的人口密度,得到「口音人群占当地人口的比例」热力图,而非单纯的样本数量热力图,这样能更真实反映口音的地理分布规律。
具体实现步骤
1. 准备两类核心数据
- 口音样本数据:包含
lat(纬度)、long(经度)的数据集,命名为accent_data。 - 美国人口密度数据:可通过
tidycensus获取普查区级别的矢量人口数据,或直接使用公开的高分辨率人口密度栅格数据(如1km分辨率)。
2. 数据匹配与归一化计算
方法一:基于普查区的矢量归一化(适合宏观区域分析)
library(tidycensus) library(tigris) library(sf) library(dplyr) # 先设置Census API密钥(需提前在普查局官网申请) census_api_key("你的API密钥") # 获取2020年美国全国普查区人口数据及地理边界 tract_pop <- get_acs(geography = "tract", variables = "B01003_001", state = NULL, year = 2020, geometry = TRUE) # 简化边界提升运算速度(可选) tract_pop <- st_simplify(tract_pop, dTolerance = 100) # 将口音样本转为空间对象 accent_sf <- st_as_sf(accent_data, coords = c("long", "lat"), crs = 4326) # 匹配样本点到普查区,计算每个普查区的口音样本占比 accent_tract <- st_join(tract_pop, accent_sf, join = st_contains) %>% group_by(GEOID) %>% summarise(accent_count = n(), total_pop = first(estimate)) %>% # 转为每万人中的口音样本数,方便可视化梯度 mutate(accent_ratio = accent_count / total_pop * 10000)
方法二:基于栅格的归一化(适合连续精细热力图)
library(terra) library(spatstat) # 加载美国人口密度栅格(可从普查局官网下载预生成文件) pop_raster <- rast("us_pop_density.tif") # 将口音样本转为点模式对象 accent_ppp <- as.ppp(accent_data, W = as.owin(pop_raster)) # 计算口音样本的核密度 accent_density <- density(accent_ppp) # 重采样人口栅格,与样本密度分辨率匹配 pop_raster_resampled <- resample(pop_raster, accent_density) # 核心归一化:口音密度除以人口密度 normalized_density <- accent_density / pop_raster_resampled
3. 绘制梯度热力图
矢量数据绘图(ggplot2)
library(ggplot2) ggplot() + geom_sf(data = accent_tract, aes(fill = accent_ratio), color = NA) + scale_fill_viridis_c(option = "plasma", name = "每万人中口音人群数") + theme_minimal() + labs(title = "美国某口音特征地理分布(人口归一化)", subtitle = "消除大城市样本偏差后的占比热力图")
栅格数据绘图(ggplot2)
ggplot() + geom_raster(data = as.data.frame(normalized_density, xy = TRUE), aes(x = x, y = y, fill = layer)) + scale_fill_viridis_c(option = "magma", name = "口音密度/人口密度") + coord_sf(crs = 4326) + theme_minimal()
关键注意事项
- 人口数据分辨率要与样本匹配:宏观分析用普查区即可,局部精细分析则用高分辨率栅格。
- 归一化后可调整缩放系数(如乘以10000),避免数值过小导致梯度不明显。
- 若无法获取Census API密钥,可直接下载普查局公开的预处理人口密度数据集,无需调用API。
内容的提问来源于stack exchange,提问作者Zeke
相关产品推荐
相关产品推荐

