Заказать бары в гистограмме ggplot2

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

    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)

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

Ответ 1

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

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

В самом общем смысле нам просто нужно установить уровни факторов в желаемом порядке. Если значение не указано, уровни фактора будут отсортированы в алфавитном порядке. Однако есть несколько способов изменить порядок на определенную последовательность в зависимости от ситуации. Например, мы могли бы сделать:

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

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

theTable$Position <- factor(theTable$Position, levels = c(...))

Ответ 2

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

ggplot(theTable,
       aes(x=reorder(Position,Position,
                     function(x)-length(x)))) +
       geom_bar()

Ответ 3

Используя scale_x_discrete (limits = ...), чтобы указать порядок столбцов.

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)

Ответ 4

Я думаю, что уже предоставленные решения чересчур многословны. Более краткий способ сделать частотный сортированный штрих-код с 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()

Ответ 5

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

Жаль, что в вопросе OP требуемый заказ также является алфавитным, поскольку это порядок сортировки по умолчанию при создании факторов, поэтому скроет, что делает эта функция. Чтобы это стало яснее, я заменил "Вратарь" на "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')

введите описание изображения здесь

Ответ 6

Простое переупорядочение факторов на основе 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

Ответ 7

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

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

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

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

Ответ 8

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

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)             

gplot output

Ответ 9

Я согласен с zach, что подсчет в 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.

Ответ 10

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

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

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

Ответ 11

Еще одна альтернатива, использующая переупорядочение для упорядочения уровней фактора. В возрастающем (n) или в убывающем порядке (-n) на основе количества. Очень похоже на использование fct_reorder из пакета forcats:

В порядке убывания

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, -n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

enter image description here

По возрастанию

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

enter image description here

Фрейм данных:

df <- structure(list(Position = structure(c(3L, 3L, 1L, 1L, 1L, 2L), .Label = c("Defense", 
"Striker", "Zoalkeeper"), class = "factor"), Name = structure(c(2L, 
1L, 3L, 5L, 4L, 6L), .Label = c("Frank", "James", "Jean", "John", 
"Steve", "Tim"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L))