如何在ggplot2点图下方添加基于n值的gear因子密度分布图?
解决方法
报错原因
geom_density()要求传入连续型的x美学映射,但你当前ggplot的主映射里x是分类变量factor(gear),且没给密度图层单独指定符合要求的x参数。另外,汇总后每组只有单个n值,数据量不足以生成密度分布,得先调整数据或换更合适的图表类型。
具体实现
推荐用patchwork包把点图和下方的统计图表上下组合,既满足布局需求,又避免双y轴带来的解读混乱:
1. 准备数据和依赖包
library(tidyverse) library(patchwork) # 生成分组汇总数据 summary_df <- mtcars %>% group_by(gear, carb) %>% summarise( avg_mpg = mean(mpg), count = n(), .groups = "drop" ) # 若要画密度图,需把分组计数还原成原始观测级数据(用于生成密度) density_raw <- summary_df %>% uncount(count)
2. 绘制上方的点图
point_plot <- ggplot(summary_df, aes(x = factor(gear), y = avg_mpg, color = factor(carb), group = carb)) + geom_point(position = position_dodge(width = 0.5)) + labs(x = "档位(Gear)", y = "平均油耗(MPG)", color = "化油器数(Carb)") + theme_minimal()
3. 绘制下方的统计图表
因为gear是分类变量,直接用密度图展示n的分布并不合适,推荐两种更贴合需求的选项:
选项A:条形图(x轴为gear,展示各carb的观测数)
最直观匹配你“x轴为gear、展示n值”的需求:
count_bar <- ggplot(summary_df, aes(x = factor(gear), y = count, fill = factor(carb))) + geom_bar(stat = "identity", position = position_dodge(width = 0.5)) + labs(x = "档位(Gear)", y = "观测数(n)", fill = "化油器数(Carb)") + theme_minimal()
选项B:密度图(展示各gear下原始数据的油耗密度,按carb着色)
如果确实需要密度图,可以展示原始数据的分布,分面按gear:
density_plot <- ggplot(density_raw, aes(x = mpg, color = factor(carb))) + geom_density() + facet_wrap(~gear, nrow = 1) + labs(x = "油耗(MPG)", y = "密度", color = "化油器数(Carb)") + theme_minimal()
4. 组合图表
用patchwork把两个图上下拼接,还能调整高度比例适配布局:
# 组合点图和条形图 point_plot / count_bar + plot_layout(heights = c(2, 1)) # 上方点图占2份高度,下方条形图占1份
关于n值缩放
如果一定要用双y轴(不推荐,易误导读者),可以通过转换因子把n值缩放到和avg_mpg匹配的范围:
ggplot(summary_df, aes(x = factor(gear))) + geom_point(aes(y = avg_mpg, color = factor(carb), group = carb), position = position_dodge(width = 0.5)) + # 用折线展示n值,先乘以缩放因子(这里用2,可根据数据调整) geom_line(aes(y = count * 2, group = factor(carb), color = factor(carb)), position = position_dodge(width = 0.5)) + scale_y_continuous( name = "平均油耗(MPG)", sec.axis = sec_axis(~./2, name = "观测数(n)") ) + labs(color = "化油器数(Carb)", x = "档位(Gear)") + theme_minimal()
内容的提问来源于stack exchange,提问作者flâneur
相关产品推荐
相关产品推荐

