Zamów słupki w wykresie słupkowym ggplot2

Próbuję zrobić wykres słupkowy, gdzie największy słupek byłby najbliższy osi y, a najkrótszy słupek byłby najdalszy. Więc to jest trochę jak stół, który mam

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

Więc staram się zbudować wykres słupkowy, który pokaże liczbę graczy w zależności od pozycji

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

Ale wykres pokazuje najpierw Pasek bramkarza, potem obronę, a na końcu napastnika. Chciałbym, aby Graf był uporządkowany tak, aby pasek obrony był najbliżej osi y, bramkarz jeden, a na koniec napastnik jeden. Dzięki

Author: Roland Ewald, 2011-03-06

10 answers

Kluczem z zamawianiem jest ustawienie poziomów czynnika w żądanej kolejności. Czynnik uporządkowany nie jest wymagany; dodatkowe informacje w czynnikiem uporządkowanym nie są konieczne i jeśli te dane są używane w dowolnym modelu statystycznym, może wyniknąć zła parametryzacja-kontrasty wielomianowe nie są odpowiednie dla danych nominalnych, takich jak ten.

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

figura barplot

W najbardziej ogólnym znaczeniu, po prostu musimy ustawić poziomy czynnika, aby były w pożądanej kolejności. Jeśli pozostawiono nieokreślone, poziomy czynnika zostaną posortowane alfabetycznie. Istnieje jednak wiele sposobów na zmianę kolejności na określoną sekwencję w zależności od sytuacji. Na przykład, możemy zrobić:

levels(theTable$Position) <- c(...)

I po prostu wymień poziomy w żądanej kolejności po prawej stronie. Możesz również określić kolejność poziomów w wywołaniu factor jak powyżej:

theTable$Position <- factor(theTable$Position, levels = c(...))
 171
Author: Gavin Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-27 18:48:48

@ GavinSimpson: reorder jest potężnym i skutecznym rozwiązaniem na to:

ggplot(theTable,
       aes(x=reorder(Position,Position,
                     function(x)-length(x)))) +
       geom_bar()
 177
Author: Alex Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-05 19:50:11

Użycie scale_x_discrete (limits = ...) do określenia kolejności słupków.

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)
 112
Author: QIBIN LI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-02 16:35:27

Myślę, że już dostarczone rozwiązania są zbyt gadatliwe. Bardziej zwięzły sposób na wykonanie sortowania częstotliwości za pomocą ggplot to

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

Jest podobny do tego, co zasugerował Alex Brown, ale nieco krótszy i działa bez żadnej definicji funkcji.

Update

Myślę, że moje stare rozwiązanie było dobre w tym czasie, ale obecnie wolałbym użyć forcats::fct_infreq, który jest sortowaniem poziomów współczynników według częstotliwości:

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()
 68
Author: Holger Brandl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-11 14:58:56

Musisz tylko określić Position kolumnę, aby była czynnikiem uporządkowanym , gdzie poziomy są uporządkowane według ich liczby:

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

(zauważ, że table(Position) tworzy liczbę częstotliwości w kolumnie Position.)

Wtedy twoja funkcja ggplot pokaże paski w malejącej kolejności liczenia. Nie wiem, czy w geom_bar jest opcja, aby to zrobić bez konieczności jawnego tworzenia uporządkowanego czynnika.

 16
Author: Prasad Chalasani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-06 14:53:46

Podobnie jak reorder() w odpowiedzi Alexa Browna, możemy również użyć forcats::fct_reorder(). Zasadniczo posortuje czynniki określone w 1. arg, zgodnie z wartościami w 2. arg po zastosowaniu określonej funkcji(domyślnie = mediana, która jest tym, czego używamy tutaj, ponieważ ma tylko jedną wartość na poziom czynnika).

Szkoda, że w pytaniu OP wymagana kolejność jest również alfabetyczna, ponieważ jest to domyślna kolejność sortowania podczas tworzenia czynników, więc ukryje to, co ta funkcja faktycznie robi. Na żeby było jaśniej, zamienię "bramkarz" na "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')

Tutaj wpisz opis obrazka

 16
Author: user2739472,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-08 13:35:47

Prosta zmiana kolejności czynników oparta na dplyr może rozwiązać ten problem:

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
 15
Author: zach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-04 14:32:17

Zgadzam się z Zachem, że liczenie w dplyr jest najlepszym rozwiązaniem. Uważam, że jest to najkrótsza wersja:

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

Będzie to również znacznie szybsze niż zmiana kolejności poziomów czynnika z wyprzedzeniem, ponieważ liczenie odbywa się w dplyr, a nie w ggplot lub za pomocą table.

 9
Author: Alexandru Papiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-04 16:29:43

Oprócz forcats:: fct_infreq, wspomniany przez @HolgerBrandl, jest forcats:: fct_rev, który odwraca kolejność czynników.

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)             

wyjście gplot

 9
Author: Robert McDonald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-25 20:19:04

Jeśli kolumny wykresu pochodzą ze zmiennej numerycznej, jak w ramce danych poniżej, możesz użyć prostszego rozwiązania:

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

Znak minus przed zmienną sortowania (-Qty) kontroluje kierunek sortowania (rosnąco / malejąco)

Oto dane do testów:

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

Kiedy znalazłem ten wątek, to była odpowiedź, której szukałem. Mam nadzieję, że to przydatne dla innych.

 3
Author: JColares,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 07:17:19