web-dev-qa-db-fra.com

Ordre des barres dans le graphique à barres ggplot2

J'essaie de faire un graphique à barres où la barre la plus grande serait la plus proche de l'axe des y et la barre la plus courte serait la plus éloignée. Donc, c'est un peu comme la table que j'ai

    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 la position

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

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

247
Julio Diaz

La clé de la commande consiste à définir les niveaux du facteur dans l'ordre de votre choix. Un facteur ordonné n'est pas nécessaire; L'information supplémentaire dans un facteur ordonné n'est pas nécessaire et si ces données sont utilisées dans n'importe quel modèle statistique, un paramétrage incorrect peut en résulter - les contrastes polynomiaux ne conviennent pas à des données nominales telles que celle-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, nous devons simplement définir les niveaux de facteurs dans l'ordre souhaité. Si non précisé, les niveaux d'un facteur seront triés par ordre alphabétique. Vous pouvez également spécifier l'ordre des niveaux dans l'appel à factoriser comme ci-dessus, et d'autres méthodes sont également possibles.

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

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

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

Utilisez 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)
122
QIBIN LI

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

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

Cela ressemble à ce que Alex Brown a suggéré, mais un peu plus court et fonctionne sans aucune définition de fonction.

Mettre à 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()
72
Holger Brandl

Comme reorder() dans la réponse d'Alex Brown, nous pourrions aussi utiliser forcats::fct_reorder(). Il va essentiellement trier les facteurs spécifiés dans le 1er argument, en fonction des valeurs du second argument après l'application d'une fonction spécifiée (par défaut = médiane, ce que nous utilisons ici comme n'ayant qu'une valeur par niveau de facteur).

Il est dommage que, dans la question du PO, l'ordre requis soit également alphabétique, puisqu'il s'agit de l'ordre de tri par défaut lorsque vous créez des facteurs, ce qui masquera donc le rôle réel de cette fonction. Pour que ce soit plus clair, je remplacerai "Gardien de but" par "Gardien de Zoal".

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

20
user2739472

Une simple réorganisation des facteurs basée sur Dplyr peut résoudre ce problème:

library(dplyr)

#reorder the table and reset the factor to that ordering
theTable %>%
  group_by(Position) %>%                              # calculate the counts
  summarize(counts = n()) %>%
  arrange(-counts) %>%                                # sort by counts
  mutate(Position = factor(Position, Position)) %>%   # reset factor
  ggplot(aes(x=Position, y=counts)) +                 # plot 
    geom_bar(stat="identity")                         # plot histogram
18
zach

Il vous suffit de spécifier que la colonne Position est un facteur ordonné où les niveaux sont classés en fonction de leur nombre:

theTable <- transform( theTable,
       Position = ordered(Position, levels = names( sort(-table(Position)))))

(Notez que table(Position) produit un compte de fréquence de la colonne Position.)

Ensuite, votre fonction ggplot affichera les barres dans l'ordre décroissant de comptage . Je ne sais pas s'il existe une option dans geom_bar pour le faire sans avoir à créer explicitement un facteur ordonné.

16
Prasad Chalasani

En plus de forcats :: fct_infreq, mentionné par @ HolgerBrandl, il existe forcats :: fct_rev, qui inverse l'ordre des facteurs.

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

p1 <- ggplot(theTable, aes(x = Position)) + geom_bar()
p2 <- ggplot(theTable, aes(x = fct_infreq(Position))) + geom_bar()
p3 <- ggplot(theTable, aes(x = fct_rev(fct_infreq(Position)))) + geom_bar()

gridExtra::grid.arrange(p1, p2, p3, nrow=3)             

 gplot output

11
Robert McDonald

Je suis d’accord avec Zach pour dire que compter dans Dplyr est la meilleure solution. J'ai trouvé que c'était la version la plus courte:

dplyr::count(theTable, Position) %>%
          arrange(-n) %>%
          mutate(Position = factor(Position, Position)) %>%
          ggplot(aes(x=Position, y=n)) + geom_bar(stat="identity")

Cela sera également beaucoup plus rapide que de réorganiser les niveaux de facteurs au préalable, car le comptage est effectué dans dplyr et non dans ggplot ou à l'aide de table.

9
Alexandru Papiu

Si les colonnes du graphique proviennent d'une variable numérique comme dans le cadre de données ci-dessous, vous pouvez utiliser une solution plus simple:

ggplot(df, aes(x = reorder(Colors, -Qty, sum), y = Qty)) 
+ geom_bar(stat = "identity")  

Le signe moins avant la variable de tri (-Qty) contrôle le sens du tri (croissant/décroissant).

Voici quelques données à tester:

df <- data.frame(Colors = c("Green","Yellow","Blue","Red","Yellow","Blue"),  
                 Qty = c(7,4,5,1,3,6)
                )

**Sample data:**
  Colors Qty
1  Green   7
2 Yellow   4
3   Blue   5
4    Red   1
5 Yellow   3
6   Blue   6

Quand j'ai trouvé ce fil, c'était la réponse que je cherchais. J'espère que c'est utile pour les autres.

7
JColares

Puisque nous ne regardons que la distribution d'une variable unique ("Position") par opposition à la relation entre deux variables, alors peut-être un histogramme le graphique le plus approprié. ggplot a geom_histogram () cela facilite les choses:

ggplot(theTable, aes(x = Position)) + geom_histogram(stat="count")

 enter image description here

Utilisation de geom_histogram ():

Je pense que geom_histogram ( ) est un peu bizarre car il traite les données continues et discrètes différemment. 

Pour données continues, vous pouvez simplement utiliser geom_histogram () sans paramètre . Par exemple, si nous ajoutons un vecteur numérique "Score" ...

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

et utilisez geom_histogram () sur la variable "Score" ...

ggplot(theTable, aes(x = Score)) + geom_histogram()

 enter image description here

Pour données discrètes comme "Position", nous devons spécifier une statistique calculée calculée par l'esthétique pour donner la valeur y à la hauteur des barres à l'aide de stat = "count":

 ggplot(theTable, aes(x = Position)) + geom_histogram(stat = "count")

Remarque: Curieusement et déroutant, vous pouvez également utiliser stat = "count" pour des données continues, ce qui fournit un graphique plus esthétique.

ggplot(theTable, aes(x = Score)) + geom_histogram(stat = "count")

 enter image description here

Edits: Réponse étendue en réponse aux suggestions utiles de DebanjanB .

1
indubitably

Une autre alternative utilisant reorder pour ordonner les niveaux d’un facteur. En ordre croissant (n) ou en ordre décroissant (-n) en fonction du nombre. Très similaire à celui utilisant fct_reorder du paquet forcats:

Ordre décroissant

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, -n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

 enter image description here

Ordre croissant

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

 enter image description here

Trame de données:

df <- structure(list(Position = structure(c(3L, 3L, 1L, 1L, 1L, 2L), .Label = c("Defense", 
"Striker", "Zoalkeeper"), class = "factor"), Name = structure(c(2L, 
1L, 3L, 5L, 4L, 6L), .Label = c("Frank", "James", "Jean", "John", 
"Steve", "Tim"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L))
0
mpalanco