Заказать столбцы в ggplot2 гистограмма - PullRequest
268 голосов
/ 06 марта 2011

Я пытаюсь сделать гистограмму, где самый большой бар будет ближайшей к оси у и самой короткой строке будет дальше. Так что это вроде как таблицы у меня есть

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

Так что я пытаюсь построить гистограмму, показывающую количество игроков в соответствии с положением

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

но график показывает вратарь бар первую затем защиту, и, наконец, один нападающий. Я хотел бы, чтобы график заказывается так что бар обороны ближе к оси у, вратарь один, и, наконец, нападающий одного. Спасибо

Ответы [ 12 ]

195 голосов
/ 10 февраля 2012

@ GavinSimpson: reorder является мощным и эффективным решением для этого:

1003 *
190 голосов
/ 06 марта 2011

Ключом к порядку является установка уровней коэффициента в нужном вам порядке.Упорядоченный фактор не требуется;дополнительная информация в упорядоченном множителе не требуется, и если эти данные используются в какой-либо статистической модели, это может привести к неправильной параметризации - полиномиальные контрасты не подходят для номинальных данных, таких как эта.

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

В самом общем смысле нам просто нужно установить уровни факторов в желаемом порядке.Если не указать, уровни фактора будут отсортированы в алфавитном порядке.Вы также можете указать порядок уровней в вызове фактора, как указано выше, также возможны и другие способы.

theTable$Position <- factor(theTable$Position, levels = c(...))
132 голосов
/ 01 декабря 2014

Использование scale_x_discrete (limits = ...) для указания порядка баров.

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)
79 голосов
/ 12 декабря 2014

Я думаю, что уже предоставленные решения слишком многословны. Более краткий способ сделать полосу сортировки по частоте с помощью ggplot -

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

Это похоже на то, что предложил Алекс Браун, но немного короче и работает без какого-либо определения функции.

Обновление

Я думаю, что мое старое решение было хорошо в то время, но в настоящее время я бы предпочел использовать forcats::fct_infreq, то есть уровни факторов сортировки по частоте:

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()
23 голосов
/ 08 декабря 2016

Как и reorder() в ответе Алекса Брауна, мы также можем использовать forcats::fct_reorder().Он будет в основном сортировать факторы, указанные в 1-м аргументе, в соответствии со значениями во 2-м аргументе после применения указанной функции (по умолчанию = медиана, что мы и здесь используем, так как просто имеем одно значение на уровень фактора).

Обидно, что в вопросе OP требуемый порядок также является алфавитным, так как это порядок сортировки по умолчанию при создании факторов, поэтому он скрывает, что на самом деле делает эта функция.Чтобы было понятнее, я заменю «Вратарь» на «Зоокейпер».

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

21 голосов
/ 29 июля 2016

Простое переупорядочение факторов на основе dplyr может решить эту проблему:

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
17 голосов
/ 06 марта 2011

Вам просто нужно указать столбец Position как упорядоченный коэффициент , где уровни упорядочены по их количеству:

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

(Обратите внимание, что table(Position) производит подсчет частоты столбца Position.)

Тогда ваша функция ggplot будет показывать столбцы в порядке убывания количества. Я не знаю, есть ли в geom_bar возможность сделать это без явного создания упорядоченного фактора.

14 голосов
/ 24 февраля 2018

В дополнение к forcats :: fct_infreq, упомянутому @HolgerBrandl, есть forcats :: fct_rev, который меняет порядок факторов.

10 голосов
/ 31 июля 2016

Я согласен с Заком, что подсчет в dplyr - лучшее решение. Я обнаружил, что это самая короткая версия:

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

Это также будет значительно быстрее, чем переупорядочение уровней факторов заранее, поскольку подсчет выполняется в dplyr, а не в ggplot или при использовании table.

9 голосов
/ 03 августа 2018

Если столбцы диаграммы взяты из числовой переменной, как в приведенном ниже кадре данных, вы можете использовать более простое решение:

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

Знак минус перед переменной сортировки (-Qty) контролирует направление сортировки (по возрастанию / по убыванию)

Вот некоторые данные для тестирования:

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

Когда я нашел эту тему, это был ответ, который я искал.Надеюсь, что это полезно для других.

...