385 votes

Ordre des barres dans le graphique à barres de ggplot2

J'essaie de créer un graphique à barres où la barre la plus grande serait la plus proche de l'axe des y et la barre la plus courte la plus éloignée. C'est un peu comme le tableau que je possède

    Name   Position
1   James  Goalkeeper
2   Frank  Goalkeeper
3   Jean   Defense
4   Steve  Defense
5   John   Defense
6   Tim    Striker

J'essaie donc de construire un graphique à barres qui montrerait le nombre de joueurs en fonction de leur position.

p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1)

mais le graphique montre d'abord la barre du gardien, puis celle de la défense, et enfin celle de l'attaquant. Je voudrais que le graphique soit ordonné de manière à ce que la barre de la défense soit la plus proche de l'axe des y, puis celle du gardien de but et enfin celle de l'attaquant. Merci

17 votes

ggplot ne peut-il pas les réorganiser pour vous sans avoir à manipuler le tableau (ou le cadre de données) ?

3 votes

@MattO'Brien Je trouve incroyable que cela ne soit pas fait en une seule commande simple.

0 votes

@Zimano Dommage que ce soit ce que vous retirez de mon commentaire. Mon observation portait sur les créateurs de ggplot2 pas l'OP

270voto

Alex Brown Points 15776

@GavinSimpson : reorder est une solution puissante et efficace pour cela :

ggplot(theTable,
       aes(x=reorder(Position,Position,
                     function(x)-length(x)))) +
       geom_bar()

7 votes

En effet +1, et surtout dans ce cas où il y a un ordre logique que nous pouvons exploiter numériquement. Si nous considérons un ordre arbitraire des catégories et que nous ne voulons pas un ordre alphabétique, il est tout aussi facile (plus facile ?) de spécifier les niveaux directement comme indiqué.

3 votes

C'est le plus beau. Nul besoin de modifier la trame de données d'origine

3 votes

Joli, je viens de remarquer que vous pouvez faire cela un peu plus succinctement, si tout ce que vous voulez est d'ordonner par la fonction longueur et que l'ordre ascendant est correct, ce qui est quelque chose que je veux souvent faire : ggplot(theTable,aes(x=reorder(Position,Position,length))+geo‌​m_bar()

255voto

Gavin Simpson Points 72349

La clé de la commande est de définir les niveaux du facteur dans l'ordre que vous souhaitez. Un facteur ordonné n'est pas nécessaire ; les informations supplémentaires dans un facteur ordonné ne sont pas nécessaires et si ces données sont utilisées dans un modèle statistique, une mauvaise paramétrisation pourrait en résulter - les contrastes polynomiaux ne sont pas appropriés pour des données nominales comme celles-ci.

## set the levels in order we want
theTable <- within(theTable, 
                   Position <- factor(Position, 
                                      levels=names(sort(table(Position), 
                                                        decreasing=TRUE))))
## plot
ggplot(theTable,aes(x=Position))+geom_bar(binwidth=1)

barplot figure

Dans le sens le plus général, il suffit de régler les niveaux de facteurs pour qu'ils soient dans l'ordre souhaité. Si rien n'est spécifié, les niveaux d'un facteur seront triés par ordre alphabétique. Vous pouvez également spécifier l'ordre des niveaux dans l'appel au facteur comme ci-dessus, et d'autres façons sont également possibles.

theTable$Position <- factor(theTable$Position, levels = c(...))

1 votes

@Gavin : 2 simplifications : puisque vous utilisez déjà within il n'est pas nécessaire d'utiliser theTable$Position et vous pourriez simplement faire sort(-table(...)) par ordre décroissant.

2 votes

@Prasad le premier était un reste de test, merci de le signaler. Pour ce qui est de la seconde, je préfère demander explicitement le tri inversé plutôt que la fonction - que vous utilisez car il est beaucoup plus facile d'obtenir l'intention de decreasing = TRUE que de remarquer le - dans tout le reste du code.

0 votes

@Gavin ok je vois ce que vous voulez dire

204voto

QIBIN LI Points 1747

Utilisation de scale_x_discrete (limits = ...) pour spécifier l'ordre des barres.

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)

106voto

Holger Brandl Points 124

Je pense que les solutions déjà fournies sont trop verbeuses. Une façon plus concise de faire un graphique en barres trié par fréquence avec ggplot est la suivante

ggplot(theTable, aes(x=reorder(Position, -table(Position)[Position]))) + geom_bar()

Elle est similaire à celle proposée par Alex Brown, mais un peu plus courte et fonctionne sans définition de fonction quelconque.

Mise à jour

Je pense que mon ancienne solution était bonne à l'époque, mais aujourd'hui je préfère utiliser forcats::fct_infreq qui consiste à trier les niveaux de facteurs par fréquence :

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()

42voto

user2739472 Points 1111

Comme reorder() dans la réponse d'Alex Brown, on pourrait aussi utiliser forcats::fct_reorder() . Il va essentiellement trier les facteurs spécifiés dans le 1er arg, selon les valeurs dans le 2ème arg après avoir appliqué une fonction spécifiée (par défaut = médiane, qui est ce que nous utilisons ici car nous avons juste une valeur par niveau de facteur).

Il est dommage que dans la question de l'OP, l'ordre requis soit également alphabétique, car c'est l'ordre de tri par défaut lorsque vous créez des facteurs, ce qui masque ce que cette fonction fait réellement. Pour que ce soit plus clair, je vais remplacer "Goalkeeper" par "Zoalkeeper".

library(tidyverse)
library(forcats)

theTable <- data.frame(
                Name = c('James', 'Frank', 'Jean', 'Steve', 'John', 'Tim'),
                Position = c('Zoalkeeper', 'Zoalkeeper', 'Defense',
                             'Defense', 'Defense', 'Striker'))

theTable %>%
    count(Position) %>%
    mutate(Position = fct_reorder(Position, n, .desc = TRUE)) %>%
    ggplot(aes(x = Position, y = n)) + geom_bar(stat = 'identity')

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X