forcer boxplots à partir de GEOM boxplot à largeur constante
je fais un boxplot dans lequel x
et fill
sont mappés à des variables différentes, un peu comme ceci:
ggplot(mpg, aes(x=as.factor(cyl), y=cty, fill=as.factor(drv))) +
geom_boxplot()
Comme dans l'exemple ci-dessus, les largeurs de mes boîtes de sortir différemment à différents x
valeurs, parce que je n'ai pas toutes les combinaisons possibles de x
et fill
valeurs, donc .
je voudrais que toutes les cases de la même largeur. Est-ce possible (idéalement sans manipuler le sous-jacent data frame, parce que je crains que l'ajout de fausses données va me causer de la confusion au cours d'une analyse plus poussée)?
Ma première pensée a été de moins de!--10-->
+ geom_boxplot(width=0.5)
mais cela n'aide pas; il ajuste la largeur de l'ensemble complet de boxplots pour un x
niveau du facteur.
Ce postpresque semble pertinent, mais je ne vois pas comment l'appliquer à ma situation. En utilisant + scale_fill_discrete(drop=FALSE)
ne semble pas modifier la largeur des barres.
1 réponses
Le problème est dû à certaines cellules de combinaisons de facteurs n'étant pas présent. Le nombre de points de données pour toutes les combinaisons des niveaux de cyl
et drv
peut être vérifié via 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
Il y a trois cellules vides. Je vais ajouter de fausses données pour contourner les problèmes de visualisation.
vérifier la plage de la variable dépendante (axe des y). Les fausses données doivent être hors de portée.
range(mpg$cty)
# [1] 9 35
Créer un sous-ensemble de mpg
avec les données nécessaires à l'intrigue:
tmp <- mpg[c("cyl", "drv", "cty")]
Créer un index pour les cellules vides:
idx <- which(tab == 0, arr.ind = TRUE)
idx
# row col
# r 3 1
# 4 1 2
# r 3 2
Créer trois faux lignes (avec -1 comme valeur de 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
Ajouter les lignes de données existantes:
tmp2 <- rbind(tmp, do.call(rbind, fakeLines))
Plot:
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.