如何用R(含tidyverse方案)计算德国邮编周边指定半径内献血点数量
基于tidyverse计算德国邮编周边献血点数量的解决方案
数据准备
先读取两个目标数据框:
德国邮编经纬度数据
# 读取德国邮编数据 Germany <- read.csv("https://gist.githubusercontent.com/MarcoKuehne/a012325ef8a9fa33aaa943dbc3db4ba9/raw/8616404bece8d405553d36380c7242fab37043d9/zipcodes.germany.csv", sep = ";")
德国献血点数据
# 读取德国献血点数据 Blooddonation <- read.csv("https://gist.githubusercontent.com/MarcoKuehne/95cc459b81f2bc6bec2f2b46d1f6273a/raw/2b1c77fe5cf1203ca105b7f61019bb390335db8e/LocationsUpdate.csv", sep=",")
需求说明
为Germany数据框新增两个变量:
donation_points_10km:该邮编位置周边10公里范围内的献血点数量donation_points_20km:该邮编位置周边20公里范围内的献血点数量
解决方案(基于tidyverse+sf)
用tidyverse处理数据流程,搭配sf包完成地理空间距离计算:
# 加载所需工具包 library(tidyverse) library(sf) # 1. 将普通数据框转换为地理空间对象(采用WGS84坐标系,EPSG:4326) germany_sf <- Germany %>% st_as_sf(coords = c("lon", "lat"), crs = 4326) blood_sf <- Blooddonation %>% st_as_sf(coords = c("lon", "lat"), crs = 4326) # 2. 转换为UTM投影(EPSG:25832,适配德国区域,单位为米) # 平面投影能避免球面坐标的距离计算误差,提升精度 germany_utm <- germany_sf %>% st_transform(crs = 25832) blood_utm <- blood_sf %>% st_transform(crs = 25832) # 3. 计算每个邮编点周边的献血点数量,并合并回原数据 germany_with_counts <- germany_utm %>% mutate( # 统计10公里范围内的献血点数量 donation_points_10km = map_int(geometry, ~sum(st_distance(.x, blood_utm) <= 10000)), # 统计20公里范围内的献血点数量 donation_points_20km = map_int(geometry, ~sum(st_distance(.x, blood_utm) <= 20000)) ) %>% # 移除地理空间属性,转回普通数据框(如需保留地理信息可跳过此步) st_drop_geometry() %>% # 合并原始Germany的所有字段 bind_cols(Germany) %>% # 调整列顺序,让新增的计数变量更直观 select(id, loc_id, zipcode, name, lat, lon, donation_points_10km, donation_points_20km) # 查看结果示例 head(germany_with_counts)
代码说明
st_as_sf:把带经纬度的普通数据框转为地理空间对象,明确坐标系st_transform:切换到UTM平面投影,解决球面坐标计算直线距离的误差问题map_int:遍历每个邮编点的地理坐标,计算与所有献血点的距离,统计符合距离阈值的数量st_drop_geometry:可选操作,若不需要保留地理空间属性,可转回常规数据框格式
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

