3
votes

ggplot: barres adjacentes groupées de largeur variable

J'essaye de produire un barplot dans lequel la largeur et la hauteur des barres véhiculent toutes deux des informations: la hauteur est le nombre d'heures passées sur une tâche, les largeurs indiquent respectivement l'aptitude perçue et importance associée à la tâche. J'ai réussi à produire cette monstruosité:

Nested Bars Plot

C'est fonctionnel mais horrible. J'aimerais vraiment placer les barres côte à côte (plutôt que de les superposer), de sorte que chaque activité soit représentée par deux barres touchantes de même hauteur (= temps passé) mais de largeurs et de couleurs différentes. J'ai essayé de passer un argument de largeur à ce tracé:

Plot w / esquivé bars

mais le réglage 'aes (width = widthVariable)' me donne des barres qui se chevauchent (similaire à la première image) et le message d'avertissement suivant:

" position_dodge ne se chevauche pas x intervalles ".

Existe-t-il un moyen de regrouper mes barres par activité, de les afficher de manière adjacente et de faire varier leur largeur?

Voici un peu le df que j'utilise:

 ggplot(molten, aes(x=Activity, y=value, fill=variable)) + geom_bar(stat='identity',aes(width = width/10))

Le deuxième graphique est le suivant:

 ggplot(molten, aes(x=Activity, y=value, fill=variable)) + geom_bar(stat='identity',position = 'dodge')

et le premier dans quelque chose comme ceci:

molten = data.frame(Activity = rep(c('Administration','Working with Colleagues','Use of Social Media','Leadership Role'),2),
            variable = c(rep('Importance',4),rep('Competence',4)),
            value = rep(c(3.02,1.71,2.39,3.32),2),
            width = c(3.48,3.52,4.01,2.98,
                      3.85,2.34,4.87,3.81))

Bien que je l'ai fait en utilisant un dataframe un peu plus simple, que j'ai fondu () dans celui ci-dessus.


0 commentaires

3 Réponses :


1
votes

Ce n'est pas une solution parfaite, mais vous pouvez créer une nouvelle colonne qui combine l'activité et la variable, l'utiliser comme x et la remplir par variable:

molten<-mutate(molten,activity=paste(Activity,variable))
ggplot(molten, aes(x=activity, y=value,width = width/10)) + 
  geom_bar(stat='identity', aes(fill=variable)) + 
  theme(axis.text.x = element_text(angle = 45,hjust=1)) + 
  scale_x_discrete(breaks=molten$activity, labels=molten$Activity)

 entrez la description de l'image ici


1 commentaires

Merci, je vais jeter un oeil à ça. Peut-être que je peux utiliser scale_x_continuous (breaks = foo, labels = unique (molten $ Activity)), puis ajuster la position de la barre manuellement (je ne sais pas si c'est possible)



0
votes

J'ai fait des progrès, en me basant sur l'idée d'iod de faire muter la trame de données d'origine. J'ai fait deux geom-bars séparés et les ai poussés l'un dans l'autre. J'adorerais vraiment que chaque barre touche son voisin, mais position_nudge () ne prend qu'une constante. J'entre toujours dans ggplot, donc la solution la plus évidente dans mon esprit est un vecteur 'nudge' recyclé, semblable à l'argument de couleur de barplot ().

tldr: Peu d'espaces entre les barres mais raisonnablement joli maintenant. P >

 Barplot amélioré. J'ai mélangé les libellés pour que les données ne soient pas publiées

 molten<-mutate(molten,activity=paste(Activity,variable))
    molten$importanceBars = c(value[variable=='Importance'],rep(0,nrow(molten)-sum(variable=='Importance')))
    molten$competenceBars = c(rep(0,nrow(molten)-sum(variable=='Competence')),value[variable=='Competence'])

ggplot(molten, aes(x=activity,width = width/6, fill = variable)) + 
  geom_bar(stat='identity', aes(y=importanceBars),position=position_nudge(x=-0.2-0.35)) +
  geom_bar(stat='identity', aes(y=competenceBars),position=position_nudge(x=-0.35)) +
  theme(axis.text.x = element_text(angle = 45,hjust=1)) + 
  scale_x_discrete(breaks=molten$activity[molten$variable=='Competence'], 
                   labels=molten$Activity[molten$variable=='Competence'])


0 commentaires

0
votes

Je l'ai fait - j'ai dû dessiner chaque barre comme un rectangle, en ajustant xmin et xmax en conséquence.

perfected barplot

wadjust = 5.5
gap = 0.0
minv = 1:length(value) - 0.5 + gap/2
maxv = minv + 1 -gap


minv[1:length(minv)%%2!=0] = maxv[1:length(maxv)%%2!=0] - width[order(Activity)][(1:length(width))%%2!=0]/wadjust
maxv[1:length(maxv)%%2==0] = minv[1:length(minv)%%2==0] + width[order(Activity)][(1:length(width))%%2==0]/wadjust

minv = minv +0.525
maxv = maxv +0.525

minvord = minv[order(Activity)]
maxvord = maxv[order(Activity)]

ggplot(molten, aes(x=activity,width = width/6, fill = variable)) + 
  geom_rect(xmin = minv,xmax = maxv, ymin = rep(0,28), ymax = value[order(Activity)],
            fill = rep(c('#e1de00','#e84619'),len=28))  + 
  theme(axis.text.x = element_text(angle = 45,hjust=1)) + 
  theme(plot.margin=unit(c(1,0.5,1,2),"cm")) +
  scale_x_discrete(breaks=molten$activity[molten$variable=='Importance'], 
                   labels=molten$Activity[molten$variable=='Importance'][order(Activity[molten$variable=='Importance'])]) +
  scale_y_continuous(labels = 0:3, breaks = 0:3, limits = c(0,3)) +
  xlab('Activity') + ylab('Hours Spent') + 
  labs(title = 'Perceived Importance & Competence\nAssociated with Clerical Duties') +
  theme(panel.grid.major.x = element_blank()) +
  geom_vline(xintercept = (maxv[1:length(maxv)%%2!=0]+minv[1:length(minv)%%2==0])/2,col='white') +
  geom_vline(xintercept = seq(len = 14, by = 2),col = 'white')


0 commentaires