Commande de l'échelle X discrète par fréquence / valeur

137

Je crée un graphique à barres esquivé en utilisant ggplot avec une échelle x discrète, l'axe des x est maintenant organisé par ordre alphabétique, mais je dois le réorganiser de sorte qu'il soit ordonné par la valeur de l'axe y (c'est-à-dire que la barre la plus haute sera être positionné à gauche).

J'ai essayé de trier ou de trier, mais j'ai réussi à trier l'axe des x, mais pas les barres respectivement.

Qu'est ce que j'ai mal fait?

lokheart
la source

Réponses:

105

Essayez de définir manuellement les niveaux du facteur sur l'axe des x. Par exemple:

library(ggplot2)
# Automatic levels
ggplot(mtcars, aes(factor(cyl))) + geom_bar()    

ggplot du jeu de données voitures avec des niveaux de facteurs déterminés automatiquement

# Manual levels
cyl_table <- table(mtcars$cyl)
cyl_levels <- names(cyl_table)[order(cyl_table)]
mtcars$cyl2 <- factor(mtcars$cyl, levels = cyl_levels)
# Just to be clear, the above line is no different than:
# mtcars$cyl2 <- factor(mtcars$cyl, levels = c("6","4","8"))
# You can manually set the levels in whatever order you please. 
ggplot(mtcars, aes(cyl2)) + geom_bar()

ggplot du jeu de données voitures avec des niveaux de facteurs réorganisés manuellement

Comme James l'a souligné dans sa réponse, reorderest la manière idiomatique de réorganiser les niveaux de facteurs.

mtcars$cyl3 <- with(mtcars, reorder(cyl, cyl, function(x) -length(x)))
ggplot(mtcars, aes(cyl3)) + geom_bar()

ggplot du jeu de données des voitures avec les niveaux de facteurs réorganisés à l'aide de la fonction de réorganisation

Coton Richie
la source
197

Le meilleur moyen pour moi était d'utiliser le vecteur avec des catégories dans l'ordre dont j'ai besoin en tant que limitsparamètre scale_x_discrete. Je pense que c'est une solution assez simple et directe.

ggplot(mtcars, aes(factor(cyl))) + 
  geom_bar() + 
  scale_x_discrete(limits=c(8,4,6))

entrez la description de l'image ici

Yuriy Petrovskiy
la source
1
@HendyIrawan il n'y a pas de légende sauf si vous avez d'autres dimensions (couleur, remplissage) également mappées à la même variable.
Gregor Thomas
5
Je pense que c'est la meilleure réponse. Il contrôle l'ordre des valeurs de l'axe des x et ne transforme ni n'affecte le bloc de données. L'utilisation factoret reordermodifie les caractéristiques des données, bien que dans le cadre de l' ggplot()appel, et cela fait plus qu'il n'en faut pour le problème en question.
mjandrews
2
Cela devrait être la réponse acceptée !! Pourquoi compliquer les choses en écrivant 2 à 3 lignes de code pour quelque chose que vous pouvez faire dans une seule ligne élégante (prédéfinie) de code?
SilSur
1
Cela a également fonctionné pour moi pour commander x par valeur de y: scale_x_discrete(limits = DT$x[order(-DT$y)])+
armipunk
38

Vous pouvez utiliser reorder:

qplot(reorder(factor(cyl),factor(cyl),length),data=mtcars,geom="bar")

Éditer:

Pour avoir la barre la plus haute à gauche, vous devez utiliser un peu de kludge:

qplot(reorder(factor(cyl),factor(cyl),function(x) length(x)*-1),
   data=mtcars,geom="bar")

Je m'attendrais à ce que cela ait également des hauteurs négatives, mais ce n'est pas le cas, donc cela fonctionne!

James
la source
5
Je suis choqué que cette réponse n'ait pas plus de votes positifs, 90% du temps, c'est la bonne façon de le faire.
Gregor Thomas
1
Je pense que les deux appels de facteurs sont superflus. Il y a un appel implicite à factor pour le premier argument et le second argument est supposé numérique.
IRTFM
Une explication qui m'a aidé à comprendre ce que ces solutions faisaient sous le capot: rstudio-pubs-static.s3.amazonaws.com
...
30

Hadley a développé un package appelé forcats. Ce package rend la tâche beaucoup plus facile. Vous pouvez l'exploiter fct_infreq()lorsque vous souhaitez modifier l'ordre de l'axe des x par la fréquence d'un facteur. Dans le cas de l' mtcarsexemple de cet article, vous souhaitez réorganiser les niveaux de cylpar la fréquence de chaque niveau. Le niveau qui apparaît le plus fréquemment reste sur le côté gauche. Tout ce dont vous avez besoin est le fct_infreq().

library(ggplot2)
library(forcats)

ggplot(mtcars, aes(fct_infreq(factor(cyl)))) +
geom_bar() +
labs(x = "cyl")

Si vous voulez faire l'inverse, vous pouvez utiliser fct_rev()avec fct_infreq().

ggplot(mtcars, aes(fct_rev(fct_infreq(factor(cyl))))) +
geom_bar() +
labs(x = "cyl") 

entrez la description de l'image ici

jazzurro
la source
2

Je me rends compte que c'est vieux, mais peut-être que cette fonction que j'ai créée est utile à quelqu'un là-bas:

order_axis<-function(data, axis, column)
{
  # for interactivity with ggplot2
  arguments <- as.list(match.call())
  col <- eval(arguments$column, data)
  ax <- eval(arguments$axis, data)

  # evaluated factors
  a<-reorder(with(data, ax), 
             with(data, col))

  #new_data
  df<-cbind.data.frame(data)
  # define new var
  within(df, 
         do.call("<-",list(paste0(as.character(arguments$axis),"_o"), a)))
}

Maintenant, avec cette fonction, vous pouvez tracer de manière interactive avec ggplot2, comme ceci:

ggplot(order_axis(df, AXIS_X, COLUMN_Y), 
       aes(x = AXIS_X_o, y = COLUMN_Y)) +
        geom_bar(stat = "identity")

Comme on peut le voir, la order_axisfonction crée une autre dataframe avec une nouvelle colonne nommée de la même manière mais avec un _oà la fin. Cette nouvelle colonne a des niveaux dans l'ordre croissant, donc ggplot2 trace automatiquement dans cet ordre.

Ceci est quelque peu limité (ne fonctionne que pour les combinaisons de caractères ou de facteurs et numériques de colonnes et dans l'ordre croissant) mais je le trouve toujours très utile pour le traçage en déplacement.

eflores89
la source
Je suppose que je ne vois pas l'avantage de cela par rapport à la simple utilisation reorderdirecte. Ne fait-il pas ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...la même chose, à peu près aussi concis, et sans la fonction d'aide?
Gregor Thomas