R语言使用cowplot对齐直方图与箱线图实现共享x轴的轴偏移解决
数据
# A tibble: 1,472 x 3 wage educ exper <dbl> <fct> <dbl> 1 7.78 1 23 2 4.82 1 15 3 10.6 1 31 4 7.04 1 32 5 7.89 1 9 6 8.20 1 15 7 8.21 1 26 8 10.4 1 23 9 11.0 1 13 10 7.21 1 22 # ... 剩余1,462行数据
直方图与箱线图的x轴对齐问题
我用cowplot包把wage列的直方图和箱线图上下排列,想让两个图共享x轴,但现在生成的图里两个图的x轴数值明显对不上,下面是可复现的完整代码:
library(tidyverse) library(cowplot) wages <- read_csv("http://vincentarelbundock.github.io/Rdatasets/csv/Ecdat/Bwages.csv") %>% select(-X1, -sex) %>% mutate(educ = factor(educ)) #> Warning: Missing column names filled in: 'X1' [1] #> #> -- Column specification -------------------------------------------------------- #> cols( #> X1 = col_double(), #> wage = col_double(), #> educ = col_double(), #> exper = col_double(), #> sex = col_logical() #> ) p1 <- ggplot(wages) + geom_histogram(aes(x = wage)) + geom_vline(xintercept = median(wages$wage), color = "red") p2 <- ggplot(wages) + geom_boxplot(aes(x = wage)) plot_grid(p1, p2, ncol = 1, axis = "l", align = 'v') #> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

代码示例由reprex包(v1.0.0版本)于2021-02-27生成
问题:怎么调整代码,才能让两个图的x轴完美对齐?
解决方案
出现错位的核心原因是两个图的x轴范围是ggplot分别自动计算的,没有强制统一,就算用plot_grid的对齐参数也没法修正数值范围本身的偏移。调整方法分三步:
- 给两个图手动指定完全一致的x轴范围,消除自动计算带来的差异
- 隐藏上方直方图的x轴所有视觉元素,避免重复展示
- 去掉两个图相邻边距,让上下图的绘图区域严丝合缝
调整后的完整可运行代码:
library(tidyverse) library(cowplot) wages <- read_csv("http://vincentarelbundock.github.io/Rdatasets/csv/Ecdat/Bwages.csv") %>% select(-X1, -sex) %>% mutate(educ = factor(educ)) # 统一计算x轴范围,提前设置统一的轴刻度 x_lim <- range(wages$wage) * c(0.95, 1.05) # 左右留少量边距,和直方图默认视觉一致 x_breaks <- pretty(x_lim, n = 8) # 上方的直方图 p1 <- ggplot(wages) + geom_histogram(aes(x = wage), bins = 30) + geom_vline(xintercept = median(wages$wage), color = "red") + # 强制统一x轴范围和刻度 scale_x_continuous(limits = x_lim, breaks = x_breaks) + # 隐藏x轴所有冗余元素 theme( axis.title.x = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(), plot.margin = margin(t = 5.5, r = 5.5, b = 0, l = 5.5, unit = "pt") # 去掉下边距 ) # 下方的横向箱线图 p2 <- ggplot(wages) + geom_boxplot(aes(x = wage, y = 1)) + # 明确y轴固定位置,消除自动计算的影响 # 用和p1完全一样的x轴设置 scale_x_continuous(limits = x_lim, breaks = x_breaks) + # 隐藏完全没用的y轴元素 theme( axis.title.y = element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank(), plot.margin = margin(t = 0, r = 5.5, b = 5.5, l = 5.5, unit = "pt") # 去掉上边距 ) # 排列两个图 plot_grid(p1, p2, ncol = 1, align = "v", axis = "l")
调整逻辑:之前的代码中,直方图会根据柱子的分布自动扩展x轴范围留边距,而一维横向箱线图会根据箱体、须线的实际位置自动计算x轴范围,两个范围哪怕有微小差异,视觉上就能看到x轴数值错位。强制把两个图的x轴limits、刻度设为完全相同的值,再移除两个图相邻的多余边距,对齐后两个图的x轴会完全对应,不会再有偏移。另外给直方图手动指定
bins = 30,可以消掉运行时弹出的默认分箱提示。
内容的提问来源于stack exchange,提问作者umair durrani
相关产品推荐
相关产品推荐

