ggplot2地图图例自定义:替换颜色刻度为城市薪资信息
解决ggplot2地图自定义图例问题
解决思路
- 删掉没用的默认填充色刻度图例
- 从数据集里筛选出被填充颜色的城市(即Real Wage在15-16区间的)
- 把这些城市的名称、名义工资、实际工资做成清晰的文本/表格,替换成新图例
具体代码实现
第一步:准备图例显示内容
先筛选目标城市,把信息格式化成整齐的文本:
library(dplyr) library(ggplot2) library(glue) # 若要做更美观的表格图例,需安装ggtext包 # install.packages("ggtext") # library(ggtext) # 筛选被填充颜色的城市,将每行信息格式化为"城市名 | 名义工资 | 实际工资" legend_lines <- dataset %>% filter(`Real Wage` >= 15 & `Real Wage` <= 16) %>% mutate(line_text = paste0(`City Name`, " | ", `Nominal Wage`, " | ", `Real Wage`)) %>% pull(line_text) # 给图例添加标题和分隔线,提升可读性 legend_content <- glue::glue(" 城市工资信息 ----------------- City Name | Nominal Wage | Real Wage ----------------- {paste(legend_lines, collapse = '\n')} ")
第二步:修改地图代码,替换图例
移除默认刻度图例,添加自定义文本图例:
right_join(prov2022, dataset, by = "COD_PROV") %>% ggplot(aes(fill = `Real Wage`)) + # 修正原代码的NA赋值逻辑,直接写NA更直观 geom_sf(data = ~ dplyr::mutate(., `Real Wage` = ifelse(`Real Wage` >= 15 & `Real Wage` <= 16, `Real Wage`, NA))) + theme_void() + # 去掉默认颜色刻度图例,保留填充色和透明设置 scale_fill_gradientn(colors = 'blue', na.value = "#00000000", guide = FALSE) + # 将自定义图例放在地图右上角,用等宽字体让列对齐更整齐 annotate("text", x = Inf, y = Inf, label = legend_content, hjust = 1, vjust = 1, size = 3, family = "mono")
可选:制作美观的表格图例
如果觉得纯文本不够规整,用ggtext生成带边框的表格图例:
# 生成HTML格式的表格内容 legend_table_html <- dataset %>% filter(`Real Wage` >= 15 & `Real Wage` <= 16) %>% mutate(table_row = paste0("<tr><td>", `City Name`, "</td><td>", `Nominal Wage`, "</td><td>", `Real Wage`, "</td></tr>")) %>% pull(table_row) %>% paste(collapse = "") %>% glue::glue(" <div style='border:1px solid #666; padding:8px; border-radius:4px; background:white;'> <h4 style='margin:0 0 5px 0;'>城市工资信息</h4> <table style='border-collapse: collapse; width:100%;'> <tr style='border-bottom:1px solid #ccc;'> <th style='text-align:left; padding:3px;'>城市名</th> <th style='text-align:left; padding:3px;'>名义工资</th> <th style='text-align:left; padding:3px;'>实际工资</th> </tr> {.} </table> </div> ") # 绘制带表格图例的地图 right_join(prov2022, dataset, by = "COD_PROV") %>% ggplot(aes(fill = `Real Wage`)) + geom_sf(data = ~ dplyr::mutate(., `Real Wage` = ifelse(`Real Wage` >= 15 & `Real Wage` <= 16, `Real Wage`, NA))) + theme_void() + scale_fill_gradientn(colors = 'blue', na.value = "#00000000", guide = FALSE) + ggtext::geom_textbox( data = data.frame(x = Inf, y = Inf), aes(x = x, y = y, label = legend_table_html), hjust = 1, vjust = 1, width = unit(3, "in"), # 可根据需求调整图例宽度 box.padding = unit(5, "pt") )
注意事项
- 移除默认图例:除了
guide = FALSE,也可以添加theme(legend.position = "none"),效果一致。 - 图例位置:
x = Inf, y = Inf配合hjust=1, vjust=1将图例固定在右上角,若遮挡地图内容,可调整x、y数值(如x = Inf - 0.5)。 - 文本对齐:纯文本图例用等宽字体(如
family="mono")能让列对齐更整齐,表格图例无需额外设置。
内容的提问来源于stack exchange,提问作者io_boh
相关产品推荐
相关产品推荐

