如何用ggplot创建双X轴(分类+连续)图表并排序分箱内的点?
问题描述
我想制作类似分箱散点样式的图表,要求每个分箱(比如X轴为“No”、Y轴为“No”的区域)内的点不再随机分布,而是基于x、y方向的连续变量排序。我已经创建了如下数据集:
Cell X-axis Y-axis X No Yes Y Yes No Z No Yes M No No
目前用geom_jitter()做出了基础图表,想知道怎么实现分箱内点的有序排列,同时想确认sec_axis能不能用来做分类轴的变换。
解决方案
1. 实现分箱内点的有序排列
要替代geom_jitter()的随机偏移,让点按连续变量排序,核心是提前给每个分箱内的点计算好固定位置:
- 先给数据集补充你用来排序的两个连续变量(比如
X_cont和Y_cont,替换成你的真实数据); - 按
X-axis和Y-axis分组,对每组内的点按连续变量排序,计算出分箱内的相对坐标:
library(dplyr) library(ggplot2) # 假设你的数据集名为df,先添加排序用的连续变量 df <- df %>% mutate(X_cont = runif(nrow(df)), # 替换成你的实际连续变量 Y_cont = runif(nrow(df))) %>% group_by(`X-axis`, `Y-axis`) %>% mutate( # 把分类轴转成连续数值,再加上排序后的偏移(0.3是控制点的分散范围,可调整) x_pos = as.integer(factor(`X-axis`)) + (rank(X_cont)/n() - 0.5)*0.3, y_pos = as.integer(factor(`Y-axis`)) + (rank(Y_cont)/n() - 0.5)*0.3 ) %>% ungroup()
- 最后用
geom_point()直接使用计算好的坐标,替代geom_jitter():
ggplot(df, aes(x = x_pos, y = y_pos)) + geom_point() + # 还原分类轴的显示样式 scale_x_continuous(breaks = 1:length(unique(df$`X-axis`)), labels = unique(df$`X-axis`)) + scale_y_continuous(breaks = 1:length(unique(df$`Y-axis`)), labels = unique(df$`Y-axis`)) + labs(x = "X-axis", y = "Y-axis")
这样每个分箱内的点就会严格按照你指定的连续变量排序,不会随机抖动。
2. 关于sec_axis用于分类轴变换的问题
sec_axis()本身是为连续轴设计的,没法直接处理分类(因子)轴。如果要做分类的次坐标轴,得手动把分类变量转成连续数值,再通过sec_axis()映射对应标签,举个例子:
ggplot(df, aes(x = as.integer(factor(`X-axis`)), y = as.integer(factor(`Y-axis`)))) + geom_point(aes(x = x_pos, y = y_pos)) + scale_x_continuous( breaks = 1:2, labels = c("No", "Yes"), # 示例:添加一个标签反转的次X轴 sec.axis = sec_axis(~., breaks = 1:2, labels = c("Yes", "No"), name = "反转X轴") ) + scale_y_continuous( breaks = 1:2, labels = c("No", "Yes") )
这种方式本质是把分类轴转换成连续数值后再处理,并非原生支持分类轴的变换,需要自己手动对应好数值和标签。
内容的提问来源于stack exchange,提问作者Mayan
相关产品推荐
相关产品推荐

