如何在分面ggplot中镜像strip.text至另一侧并自定义标签
问题需求
我正在处理9个调查项目(q1至q9)的数据,所有项目均采用11点量表测量对陈述的同意/不同意程度,已将数据转换为长格式方便可视化。我想绘制类似ggridges的分面密度图(因ggridges灵活性不足未使用),目前已完成基础绘图,还需要实现两个需求:
- 将分面标签(strip.text)镜像到绘图右侧
- 将分面标签替换为对应项目的同意/不同意选项文本
当前代码
theme_set(theme_minimal()) ggplot(df, aes(x = value, y = ..count.., fill = name)) + geom_density(color = "transparent") + facet_grid(name ~ ., switch = "y") + scale_fill_viridis_d(direction = -1, guide = "none") + labs(x="", y="") + xlim(-1, 13) + theme(panel.grid.minor = element_blank(), axis.text.y = element_blank(), strip.text.y.left = element_text(angle = 0, vjust = 0), strip.text.y.right = element_text(angle = 0, vjust = 0))
示例数据
structure(list(name = c("q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9"), value = structure(c(8, 1, 3, 9, 4, 11, 3, 10, 6, 5, 1, 11, 8, 1, 7, 8, 9, 5, 4, 8, 6, 6, 8, 7, 4, 6, 5, 1, 3, 11, 9, 9, 6, 4, 10, 4, 7, 3, 5, 9, 6, 9, 6, 10, 8, 1, 3, 6, 8, 6, 11, 11, 11, 11, 3, 3, 1, 6, 9, 11, 6, 11, 8, 3, 9, 11, 1, 3, 11, 11, 3, 11, 5, 4, 11, 2, 8, 10, 6, 6, 9, 6, 10, 5, 6, 11, 10, 3, 8, 1)), left = c("增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令", "增加社会支出", "投资气候领域", "增加对乌克兰援助", "促进移民", "更多公平与多元化", "增加对富裕家庭的援助", "更多监控以提升安全", "深化欧洲一体化", "保留口罩强制令"), right = c("减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令", "减少社会支出", "投资经济领域", "保持中立", "限制移民", "社会公平已实现", "减少对富裕家庭的援助", "减少监控以提升自由", "欧洲一体化过度", "取消口罩强制令")), row.names = c(NA, -90L), class = c("tbl_df", "tbl", "data.frame"))
解决方案
步骤1:预处理数据生成自定义分面标签
先提取每个项目对应的同意/不同意选项对,生成唯一的分面标签,避免重复计算:
# 提取每个项目的唯一选项对,拼接成分面标签 label_map <- df %>% distinct(name, left, right) %>% mutate(facet_label = paste(left, "\nvs.\n", right)) # 将标签映射合并到原数据 df <- df %>% left_join(label_map, by = c("name", "left", "right"))
步骤2:修改绘图代码实现需求
theme_set(theme_minimal()) ggplot(df, aes(x = value, y = ..count.., fill = name)) + geom_density(color = "transparent") + # 使用自定义标签分面,switch="y"将标签移至y轴外侧 facet_grid(facet_label ~ ., switch = "y", scales = "free_y", space = "free_y") + scale_fill_viridis_d(direction = -1, guide = "none") + labs(x = "", y = "") + xlim(-1, 13) + theme( panel.grid.minor = element_blank(), axis.text.y = element_blank(), # 隐藏左侧默认标签 strip.text.y.left = element_blank(), # 设置右侧标签样式:水平显示、左对齐 strip.text.y.right = element_text(angle = 0, vjust = 0.5, hjust = 0, lineheight = 1.2), # 将标签放在绘图区域外侧,避免遮挡 strip.placement = "outside" )
关键说明
- 自定义分面标签:通过拼接每个项目的
left(同意方向)和right(不同意方向)文本,生成带换行的对比标签,让分面直接展示调查选项。 - 镜像标签到右侧:利用
switch="y"将分面标签移到y轴外侧,隐藏左侧标签后,仅保留并配置右侧标签的样式,配合strip.placement="outside"确保标签完整显示。
内容的提问来源于stack exchange,提问作者Dr. Fabian Habersack
相关产品推荐
相关产品推荐

