Ordnen Sie die diskrete x-Skala nach Frequenz / Wert

137

Ich mache ein ausgewichenes Balkendiagramm mit ggplot mit diskreter x-Skala. Die x-Achse ist jetzt in alphabetischer Reihenfolge angeordnet, aber ich muss es neu anordnen, damit es nach dem Wert der y-Achse geordnet ist (dh der höchste Balken wird links positioniert sein).

Ich habe versucht, zu ordnen oder zu sortieren, aber die x-Achse zu sortieren, aber nicht die Balken.

Was habe ich falsch gemacht?

lokheart
quelle

Antworten:

105

Versuchen Sie, die Pegel des Faktors auf der x-Achse manuell einzustellen. Beispielsweise:

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

ggplot des Fahrzeugdatensatzes mit automatisch ermittelten Faktorstufen

# 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 des Fahrzeugdatensatzes mit manuell neu geordneten Faktorstufen

Wie James in seiner Antwort hervorhob, reorderist dies die idiomatische Art, Faktorstufen neu zu ordnen.

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

ggplot des Fahrzeugdatensatzes mit Faktorstufen, die mithilfe der Neuordnungsfunktion neu angeordnet wurden

Richie Cotton
quelle
196

Der beste Weg für mich war, Vektor mit Kategorien zu verwenden, um sie als limitsParameter zu benötigen scale_x_discrete. Ich denke, es ist eine ziemlich einfache und unkomplizierte Lösung.

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

Geben Sie hier die Bildbeschreibung ein

Yuriy Petrovskiy
quelle
1
@HendyIrawan Es gibt keine Legende, es sei denn, Sie haben andere Dimensionen (Farbe, Füllung), die ebenfalls derselben Variablen zugeordnet sind.
Gregor Thomas
5
Ich denke, das ist die beste Antwort. Es steuert die Reihenfolge der x-Achsenwerte und transformiert oder beeinflusst den Datenrahmen nicht. Durch die Verwendung factorund reorderÄnderung der Eigenschaften der Daten, wenn auch innerhalb des ggplot()Anrufs, wird mehr getan, als für das jeweilige Problem erforderlich ist.
mjandrews
2
Dies sollte die akzeptierte Antwort sein !! Warum sollten Sie die Dinge komplizieren, indem Sie 2 bis 3 Codezeilen für etwas schreiben, das Sie in einer einzigen eleganten (vordefinierten) Codezeile tun können?
SilSur
1
Dies funktionierte auch für mich, um x nach dem Wert von y zu bestellen: scale_x_discrete(limits = DT$x[order(-DT$y)])+
Armipunk
38

Sie können verwenden reorder:

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

Bearbeiten:

Um die höchste Leiste links zu haben, müssen Sie ein bisschen Kludge verwenden:

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

Ich würde erwarten, dass dies auch negative Höhen hat, aber das tut es nicht, also funktioniert es!

James
quelle
5
Ich bin schockiert, dass diese Antwort nicht mehr positive Stimmen hat. In 90% der Fälle ist dies der richtige Weg, dies zu tun.
Gregor Thomas
1
Ich halte beide Faktoraufrufe für überflüssig. Es gibt einen impliziten Aufruf zum Faktor für das erste Argument, und das zweite Argument wird als numerisch angenommen.
IRTFM
Eine Erklärung, die mir half herauszufinden, was diese Lösungen unter der Haube taten
keithpjolley
30

Hadley hat ein Paket namens entwickelt forcats. Dieses Paket macht die Aufgabe so viel einfacher. Sie können ausnutzen, fct_infreq()wenn Sie die Reihenfolge der x-Achse um die Häufigkeit eines Faktors ändern möchten. Im Fall des mtcarsBeispiels in diesem Beitrag möchten Sie die Ebenen cylnach der Häufigkeit der einzelnen Ebenen neu anordnen . Die am häufigsten angezeigte Ebene bleibt auf der linken Seite. Alles was Sie brauchen ist das fct_infreq().

library(ggplot2)
library(forcats)

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

Wenn Sie in die andere Richtung gehen möchten, können Sie fct_rev()zusammen mit verwenden fct_infreq().

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

Geben Sie hier die Bildbeschreibung ein

Jazzurro
quelle
2

Mir ist klar, dass dies alt ist, aber vielleicht ist diese Funktion, die ich erstellt habe, für jemanden da draußen nützlich:

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

Mit dieser Funktion können Sie nun interaktiv mit ggplot2 wie folgt zeichnen:

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

Wie zu sehen ist, erstellt die order_axisFunktion einen weiteren Datenrahmen mit einer neuen Spalte mit demselben Namen, jedoch mit einem _oam Ende. Diese neue Spalte enthält Ebenen in aufsteigender Reihenfolge, sodass ggplot2 automatisch in dieser Reihenfolge gezeichnet wird.

Dies ist etwas eingeschränkt (funktioniert nur für Zeichen- oder Faktor- und Zahlenkombinationen von Spalten und in aufsteigender Reihenfolge), aber ich finde es immer noch sehr nützlich für das Plotten unterwegs.

eflores89
quelle
Ich glaube, ich sehe keinen Vorteil darin, nur reorderdirekt zu verwenden. ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...Tun Sie nicht das Gleiche, ungefähr so ​​präzise und ohne die Hilfsfunktion?
Gregor Thomas