强制从geom_boxplot到常量宽度的箱形图

Dre*_*een 13 r ggplot2 boxplot

我正在制作一个箱形图,其中xfill映射到不同的变量,有点像这样:

ggplot(mpg, aes(x=as.factor(cyl), y=cty, fill=as.factor(drv))) + 
    geom_boxplot()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如上例所示,我的框的宽度在不同的x值上有所不同,因为我没有所有可能的组合xfill值,所以.

我希望所有的盒子宽度相同.可以这样做(理想情况下不需要操纵底层数据框,因为我担心添加假数据会在进一步分析时引​​起混淆)?

我的第一个想法是

+ geom_boxplot(width=0.5)
Run Code Online (Sandbox Code Playgroud)

但这没有用; 它调整给定x因子水平的整套箱图的宽度.

这篇文章 几乎看起来很相关,但我不太清楚如何将它应用到我的情况中.使用+ scale_fill_discrete(drop=FALSE)似乎不会改变条的宽度.

Sve*_*ein 2

问题是由于某些因素组合的单元格不存在。cyl和级别的所有组合的数据点数量drv可以通过以下方式检查xtabs

tab <- xtabs( ~ drv + cyl, mpg)

tab

#    cyl
# drv  4  5  6  8
#   4 23  0 32 48
#   f 58  4 43  1
#   r  0  0  4 21
Run Code Online (Sandbox Code Playgroud)

有三个空单元格。我将添加虚假数据来覆盖可视化问题。

检查因变量(y 轴)的范围。假数据需要超出这个范围。

range(mpg$cty)
# [1]  9 35
Run Code Online (Sandbox Code Playgroud)

mpg使用绘图所需的数据创建 的子集:

tmp <- mpg[c("cyl", "drv", "cty")]
Run Code Online (Sandbox Code Playgroud)

为空单元格创建索引:

idx <- which(tab == 0, arr.ind = TRUE)

idx

#   row col
# r   3   1
# 4   1   2
# r   3   2
Run Code Online (Sandbox Code Playgroud)

创建三个假行(使用 -1 作为 的值cty):

fakeLines <- apply(idx, 1,
                   function(x) 
                     setNames(data.frame(as.integer(dimnames(tab)[[2]][x[2]]), 
                                         dimnames(tab)[[1]][x[1]], 
                                         -1), 
                              names(tmp)))

fakeLines

# $r
#   cyl drv cty
# 1   4   r  -1
# 
# $`4`
#   cyl drv cty
# 1   5   4  -1
# 
# $r
#   cyl drv cty
# 1   5   r  -1
Run Code Online (Sandbox Code Playgroud)

将行添加到现有数据:

tmp2 <- rbind(tmp, do.call(rbind, fakeLines))
Run Code Online (Sandbox Code Playgroud)

阴谋:

library(ggplot2)
ggplot(tmp2, aes(x = as.factor(cyl), y = cty, fill = as.factor(drv))) + 
  geom_boxplot() +
  coord_cartesian(ylim = c(min(tmp$cty - 3), max(tmp$cty) + 3))
  # The axis limits have to be changed to suppress displaying the fake data.
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述