如何将ggplot散点图点大小按组内回答占比设置?
问题描述
我用ggplot绘制两组调查响应的散点图,当前点大小基于每组的回答计数,但两组样本量差异大,导致其中一组的点始终更大。我需要把点大小改为每组内选择特定回答选项的个体占比:针对21个gain问题,分别计算西班牙裔/非西班牙裔群体对1-5分value的回答占比,并将该占比作为散点图的点大小。
当前代码:
ggplot(data, aes(y = value, x = gain, group = demographic, color = demographic)) + geom_count(position = position_dodge(width = 0.9))
数据结构:
structure(list(hispanic = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), levels = c("hispanic", "non_hispanic"), class = "factor"), gain = c("SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16", "SU_11_15", "SU_11_16"), value = c(5, 5, 5, 5, 4, 4, 5, NA, 5, 4, NA, NA, 4, 2, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 3, 3, 3, 2, 4, 4, 5, 5, NA, NA, 4, 3, 3, NA, 4, 3, 2, 4, 3, 1, 5, 3, NA, NA, 4, 2, 5, 4, 3, 3, 2, 2, 5, 3, 5, 5, 5, NA, 3, 1, 3, 3, 5, 5, 3, 1, 5, 3, 5, 5, 4, 3, 4, 4, 5, 3, 5, 5, 5, 5, 5, 3, 4, 3, 4, 3, 5, 4, 4, 2, 4, 3, 5, 3, 5, 4, 4, 3, 4, 2, 5, 5, 5, 5, 4, 4, 4, 3, 1, 1, 5, 5, 5, 3, 5, 3, 3, 3, 5, 3, 3, 2, 5, 5, 5, 3, 5, 3, 4, 4, 5, 3)), row.names = c(NA, -138L), class = c("tbl_df", "tbl", "data.frame"))
解决方案
核心思路是先预处理数据计算每组内的占比,再用geom_point替代geom_count来指定点大小为计算好的占比。
步骤1:计算每组内的回答占比
用dplyr分组统计,过滤缺失值后,按群体、问题、回答分值分组计数,再计算每个分组在所属群体-问题组内的占比:
library(dplyr) data_summary <- data %>% filter(!is.na(value)) %>% group_by(hispanic, gain, value) %>% summarise(count = n(), .groups = "drop_last") %>% mutate(prop = count / sum(count)) %>% ungroup()
步骤2:绘制散点图
用geom_point将点大小映射为计算好的占比,保留分组颜色映射并设置点偏移避免重叠:
library(ggplot2) ggplot(data_summary, aes(x = gain, y = value, color = hispanic, size = prop)) + geom_point(position = position_dodge(width = 0.9)) + scale_size_continuous(range = c(2, 10), name = "组内占比") + labs(x = "调查问题", y = "回答分值", color = "群体") + theme(axis.text.x = element_text(angle = 45, hjust = 1))
关键说明
- 替换
geom_count为geom_point:geom_count自动统计计数,而我们需要手动传入自定义的占比数据,geom_point更灵活。 - 占比计算逻辑:按群体和问题分组后,每个回答分值的计数除以该组总计数,确保点大小只反映组内相对占比,不受两组样本量差异影响。
scale_size_continuous:可自定义点的大小范围,让占比差异更直观,同时设置图例名称提升可读性。
内容的提问来源于stack exchange,提问作者Matthew Murray
相关产品推荐
相关产品推荐

