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
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)
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(...))
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()
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)
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()
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.
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')
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
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
.
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)
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.
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