如何用data.frame/tibble指定ggplot中scale_x_continuous的刻度?
嘿,我来帮你搞定这个分面密度图自定义刻度的需求!
首先咱们先把你的初始代码整理成可重现的版本,确保咱们在同一个基础上:
library(tidyverse) set.seed(123) # 生成数据 vary_1 <- c(exp(rnorm(250, 5, 1)), rnorm(250, 10, 10), exp(rnorm(250, 20, 1)), exp(rnorm(250, 30, 1))) vary_2 <- rep(c('A', 'B', 'C', 'D'), each = 250) df <- data_frame(vary_1, vary_2) # 初始绘图 p <- df %>% ggplot(aes(vary_1, color = vary_2, fill = vary_2)) + geom_density(alpha = 0.3) + # 加个透明度方便查看填充效果 facet_wrap(~vary_2, scales = 'free') p
接下来,要实现根据数据框中的值为每个分面指定自定义刻度,这里给你两种可行的方法,按需选择:
方法一:用ggh4x包(推荐,灵活省心)
这个包专门解决ggplot分面的自定义轴刻度问题,用起来特别顺手。
首先安装并加载包:
install.packages("ggh4x") library(ggh4x)
然后咱们先从数据里提取每个分组的关键值作为刻度——比如取每个分组的最小值、中位数、最大值,你也可以换成你需要的任意值:
# 从数据框计算每个分组的自定义刻度 custom_breaks <- df %>% group_by(vary_2) %>% summarise( breaks = list(c(min(vary_1), median(vary_1), max(vary_1))), .groups = 'drop' ) %>% deframe() # 转成分组名对应刻度的列表
最后把这个刻度列表应用到分面图里:
p + facetted_pos_scales( x = list( vary_2 == "A" ~ scale_x_continuous(breaks = custom_breaks$A), vary_2 == "B" ~ scale_x_continuous(breaks = custom_breaks$B), vary_2 == "C" ~ scale_x_continuous(breaks = custom_breaks$C), vary_2 == "D" ~ scale_x_continuous(breaks = custom_breaks$D) ) )
这样每个分面就会使用咱们从数据里提取的专属刻度啦!
方法二:手动指定(无需额外安装包)
如果你不想装新包,也可以手动处理——前提是每个分面的x轴范围不重叠(你的数据刚好满足这个条件):
# 先手动生成每个分组的刻度列表(可以是从数据里算的,也可以是你指定的固定值) custom_breaks <- df %>% group_by(vary_2) %>% summarise( breaks = list(c(min(vary_1), median(vary_1), max(vary_1))), .groups = 'drop' ) %>% deframe() # 应用到绘图中 p + scale_x_continuous( breaks = function(x) { # 根据当前分面的x范围匹配对应的分组刻度 group <- names(custom_breaks)[sapply(custom_breaks, function(b) all(range(x) == range(b)))] custom_breaks[[group]] } )
额外小技巧:手动指定固定刻度
如果你不想从数据里计算,而是想直接指定每个分组的刻度值,只需要修改custom_breaks就行,比如:
custom_breaks_manual <- list( A = c(50, 100, 150, 200), B = c(-20, 0, 20, 40), C = c(1e8, 2e8, 3e8), D = c(1e12, 1.5e12, 2e12) ) # 同样用ggh4x应用 p + facetted_pos_scales( x = list( vary_2 == "A" ~ scale_x_continuous(breaks = custom_breaks_manual$A), vary_2 == "B" ~ scale_x_continuous(breaks = custom_breaks_manual$B), vary_2 == "C" ~ scale_x_continuous(breaks = custom_breaks_manual$C), vary_2 == "D" ~ scale_x_continuous(breaks = custom_breaks_manual$D) ) )
这样就能完全按照你的需求自定义每个分面的轴刻度啦!
内容的提问来源于stack exchange,提问作者elliot
相关产品推荐
相关产品推荐

