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()

enter image description here

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.

11
demandé sur Community 2013-05-23 07:22:09

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.

enter image description here

1
répondu Sven Hohenstein 2013-05-23 06:46:12