R ggplot2绘制水平点图如何添加右侧次坐标轴映射第三个变量
问题说明
在R中使用ggplot2绘制水平点图时,数据集包含3个数值型变量与1个分类变量,当前已完成映射:
- 分类变量
origin映射到y轴 - 数值变量
change、rate以带数值标注的圆点形式在主x轴展示 - 需要将第三个数值变量
Percentage映射到图右侧,对齐每个分类行展示对应数值,添加次坐标轴标注。
原始可复现代码如下:
df <- data.frame (origin = c("A","B","C","D","E","F","G","H","I","J"), Percentage = c(23,16,32,71,3,60,15,21,44,60), rate = c(10,12,20,200,-25,12,13,90,-105,23), change = c(10,12,-5,12,6,8,0.5,-2,5,-2)) library(ggplot2) ggplot(df, aes(x = rate, y = factor(origin, rev(origin)))) + geom_hline(aes(yintercept = origin), color = 'gray') + geom_vline(xintercept = 0, linetype = 2, color = 'gray') + geom_point(aes(color = 'Rate'), size = 10) + geom_text(aes(label = rate), color = 'white') + geom_point(aes(x = change, color = 'Change'), size = 10) + geom_text(aes(label = change, x = change)) + theme_minimal(base_size = 16) + scale_x_continuous(labels = ~paste0(.x, '%'), name = NULL) + scale_color_manual(values = c('#aac7c4', '#5f9299')) + theme(panel.grid = element_blank(), axis.text.y = element_text(color = 'gray50')) + labs(color = NULL, y = NULL)
当前输出效果:
预期输出效果:
实现方案
ggplot2次坐标轴需要和主轴满足线性映射关系,分类y轴无法直接关联数值次轴,按以下步骤修改即可:
- 先把分类y轴转为数值位置索引,保留原有分类排序,主y轴刻度仍展示原分类标签
- 扩展主x轴右侧范围,预留
Percentage数值的展示空间 - 在x轴最右侧的固定位置,对齐每个分类的y坐标添加
Percentage文本标注 - 添加右侧次y轴,仅保留"Percentage"标题作为列说明,隐藏多余刻度
修改后的完整代码:
df <- data.frame (origin = c("A","B","C","D","E","F","G","H","I","J"), Percentage = c(23,16,32,71,3,60,15,21,44,60), rate = c(10,12,20,200,-25,12,13,90,-105,23), change = c(10,12,-5,12,6,8,0.5,-2,5,-2)) library(ggplot2) # 计算y轴位置索引,保持原有分类排序 df$y_pos <- match(df$origin, rev(df$origin)) ggplot(df, aes(x = rate, y = y_pos)) + geom_hline(aes(yintercept = y_pos), color = 'gray') + geom_vline(xintercept = 0, linetype = 2, color = 'gray') + geom_point(aes(color = 'Rate'), size = 10) + geom_text(aes(label = rate), color = 'white') + geom_point(aes(x = change, color = 'Change'), size = 10) + geom_text(aes(label = change, x = change)) + # 右侧添加Percentage数值标注 geom_text(aes(x = 220, label = paste0(Percentage, "%")), size = 5, color = "gray30") + theme_minimal(base_size = 16) + scale_x_continuous( labels = ~paste0(.x, '%'), name = NULL, # 扩展x轴范围,左侧留边距、右侧留标注空间 limits = c(-120, 240) ) + scale_y_continuous( breaks = 1:10, labels = rev(df$origin), name = NULL, # 添加右侧次坐标轴,仅显示标题 sec.axis = sec_axis(~., name = "Percentage", breaks = NULL, labels = NULL) ) + scale_color_manual(values = c('#aac7c4', '#5f9299')) + theme( panel.grid = element_blank(), axis.text.y = element_text(color = 'gray50'), # 调整右侧次轴标题为横向,放在右上角位置 axis.title.y.right = element_text(angle = 0, vjust = 1.02, hjust = 0, margin = margin(l = 8)) ) + labs(color = NULL)
运行代码后即可得到和预期一致的输出效果,右侧对齐展示每个分类对应的Percentage数值,次轴标题清晰说明列含义,原有图表元素完全保留。
内容的提问来源于stack exchange,提问作者user18948933
相关产品推荐
相关产品推荐

