如何用R的maps包合并意大利省级边界为大区?ggplot2绘图求建议
解决意大利大区地图合并与ggplot2绘图问题
我来帮你一步步搞定这个问题,刚好之前处理过类似的意大利省级地图聚合为大区的需求,下面是具体的解决方案和绘图建议:
1. 先搞定省份到大区的映射关系
因为maps包的map_data('italy')里的region列是省份名称,而你的数据是按大区聚合的,所以第一步需要建立「省份→大区」的对应表。你可以手动整理一个,也可以参考意大利官方的行政区划来补全,这里给你一个示例片段:
# 创建省份-大区映射表(记得补全所有意大利省份) province_to_region <- data.frame( province = c("Milano", "Bergamo", "Roma", "Napoli", "Torino", "Bozen", "Firenze"), region = c("Lombardia", "Lombardia", "Lazio", "Campania", "Piemonte", "Trentino-Alto Adige", "Toscana") )
2. 合并地图数据并重新分组
接下来用dplyr把映射表和你的地图数据合并,然后给每个大区分配唯一的分组ID——这就是你想的「修改group列」的思路,让同一大区的所有省份共享同一个group值,这样ggplot绘制时就会自动合并它们的边界:
library(dplyr) library(ggplot2) # 加载原始省级地图数据 it_map <- map_data('italy') # 合并映射表并创建大区分组 it_map_region <- it_map %>% # 按省份名称合并大区信息 left_join(province_to_region, by = c("region" = "province")) %>% # 重命名列,避免混淆(原来的region是省份,现在region.y是大区) rename(province = region, region = region.y) %>% # 为每个大区生成唯一的group ID mutate(region_group = as.integer(factor(region)))
3. 处理你的业务数据:计算全时段总和
假设你的数据集叫italy_time_data,行是时间范围,列是各个大区。你需要计算每个大区的全时段总和,整理成「大区名称→总和数值」的格式:
# 计算每列(大区)的总和,整理为数据框 italy_total <- data.frame( region = colnames(italy_time_data), total_value = colSums(italy_time_data, na.rm = TRUE) ) # 重要提醒:确保这里的大区名称和地图数据里的完全一致! # 比如大小写、重音符号(像"Trentino-Alto Adige"不能少了连字符)
4. 合并数据并绘制大区地图
现在把处理好的地图数据和总和数据合并,用ggplot2绘制最终的地图:
# 合并地图与数值数据 it_combined <- it_map_region %>% left_join(italy_total, by = "region") # 绘制美观的大区地图 ggplot(it_combined, aes(x = long, y = lat, group = region_group, fill = total_value)) + # 绘制多边形,白色细边界区分大区 geom_polygon(color = "white", linewidth = 0.3) + # 使用合适的地图投影,避免变形 coord_map() + # 用简洁的主题 theme_minimal() + # 设置标题和标签 labs( title = "意大利各大区全时段数据总和", fill = "累计数值", x = "", y = "" ) + # 调整主题细节,让地图更清爽 theme( plot.title = element_text(hjust = 0.5, size = 16, face = "bold"), legend.position = "right", axis.text = element_blank(), # 去掉坐标轴刻度 panel.grid = element_blank() # 去掉网格线 ) + # 色盲友好的配色方案 scale_fill_viridis_c(option = "plasma")
5. 额外优化建议
偷懒替代方案:如果手动整理省份映射太麻烦,可以用
giscoR包直接获取意大利官方的大区边界数据,省掉合并省份的步骤:library(giscoR) # 直接获取意大利大区边界(nuts_level=1对应大区) it_regions_sf <- gisco_get_nuts(country = "IT", nuts_level = 1)用
sf格式的数据配合geom_sf()绘图会更简单,而且数据精度更高。ggplot2美观技巧:
- 配色优先选色盲友好的:比如
viridis、scico包的配色,别用红-绿搭配; - 用
theme_void()代替theme_minimal()可以完全去掉背景,更专注地图本身; - 如果大区名称需要标注,可以加
geom_text(),用大区的中心坐标来放置标签; - 给地图添加一个小的边框,比如用
theme(panel.border = element_rect(color = "black", fill = NA))。
- 配色优先选色盲友好的:比如
内容的提问来源于stack exchange,提问作者asyd
相关产品推荐
相关产品推荐

