Упорядкуйте дискретну шкалу x за частотою / значенням


137

Я роблю ухилену діаграму, використовуючи ggplot з дискретною шкалою x, вісь x тепер розташована в алфавітному порядку, але мені потрібно переставити її так, щоб вона була впорядкована за значенням осі y (тобто найвища смуга буде розташовувати зліва).

Я спробував замовити чи сортувати, але в результаті сортуйте вісь x, але не смужки відповідно.

Що я зробив неправильно?

Відповіді:


105

Спробуйте вручну встановити рівні коефіцієнта на осі x. Наприклад:

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

ggplot набору даних про автомобілі з рівнем факторів визначається автоматично

# 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 набору даних про автомобілі з рівнем факторів, упорядкованим вручну

Як зазначив Джеймс у своїй відповіді, reorderце ідіоматичний спосіб упорядкування рівнів факторів.

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

ggplot набору даних про автомобілі з рівнями факторів, упорядкованими за допомогою функції упорядкування


197

Найкращим способом для мене було використання вектора з категоріями для того, щоб мені потрібно як limitsпараметр scale_x_discrete. Я думаю, що це досить просте і зрозуміле рішення.

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

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


1
@HendyIrawan немає легенди, якщо у вас інші розміри (колір, заливка) також не відображаються в одній змінній.
Грегор Томас

5
Я думаю, що це найкраща відповідь. Він контролює порядок значень осі x і не перетворює та не впливає на кадр даних. Використання factorта reorderзміна характеристик даних, хоча і в межах ggplot()виклику, і так робить більше, ніж потрібно для проблеми, що існує.
mjandrews

2
Це має бути прийнята відповідь !! Навіщо ускладнювати речі, написавши 2 - 3 рядки коду для того, що ви можете зробити в одному елегантному (заздалегідь визначеному) рядку коду?
SilSur

1
Це також працювало для мене, щоб замовити х за значенням y: scale_x_discrete(limits = DT$x[order(-DT$y)])+
armipunk

38

Ви можете використовувати reorder:

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

Редагувати:

Щоб мати найвищу смужку ліворуч, ви повинні використовувати трохи кляття:

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

Я б очікував, що це також має негативну висоту, але це не так, так це працює!


5
Я вражений, що ця відповідь не має більшої кількості результатів, 90% часу це правильний спосіб зробити це.
Грегор Томас

1
Я думаю, що обидва факторні дзвінки є зайвими. Існує неявний виклик фактору для першого аргументу, а другий аргумент hte вважається числовим.
IRTFM

Пояснення, яке допомогло мені зрозуміти, що ці рішення роблять під кришкою: rstudio-pubs-static.s3.amazonaws.com/…
keithpjolley

30

Хедлі розробляє пакет під назвою forcats. Цей пакет значно спрощує завдання. Ви можете використовувати, fct_infreq()коли хочете змінити порядок осі x за частотою коефіцієнта. У випадку mtcarsприкладу в цій публікації потрібно змінити впорядкованість рівнів cylза частотою кожного рівня. Рівень, який з’являється найчастіше, залишається зліва. Все, що вам потрібно - це fct_infreq().

library(ggplot2)
library(forcats)

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

Якщо ви хочете піти навпаки, ви можете використовувати fct_rev()разом з fct_infreq().

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

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


2

Я усвідомлюю, що це стара, але, можливо, ця функція, яку я створив, корисна комусь там:

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

Тепер за допомогою цієї функції ви можете інтерактивно побудувати графік з ggplot2, як це:

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

Як видно, order_axisфункція створює інший фрейм даних з новим стовпцем, названим таким же, але з а _oв кінці. Цей новий стовпець має рівні у порядку зростання, тому ggplot2 автоматично розміщує в цьому порядку.

Це дещо обмежено (працює лише для символьних чи факторних та числових комбінацій стовпців та у порядку зростання), але я все ще вважаю це дуже корисним для побудови графіків на ходу.


Я думаю, я не бачу переваги в цьому порівнянні, ніж просто reorderбезпосередньо. Не ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...робиться те ж саме, приблизно так стисло і без функції помічника?
Грегор Томас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.