Urutkan skala x diskrit berdasarkan frekuensi / nilai

138

Saya membuat diagram batang dodged menggunakan ggplot dengan skala x diskrit, sumbu x sekarang disusun dalam urutan abjad, tetapi saya perlu mengatur ulang sehingga diurutkan berdasarkan nilai sumbu y (yaitu, batang tertinggi akan diposisikan di sebelah kiri).

Saya mencoba memesan atau mengurutkan, tetapi menghasilkan mengurutkan sumbu x, tetapi tidak pada batang masing-masing.

Apa yang telah saya lakukan salah?

lokheart
sumber

Jawaban:

106

Coba atur secara manual tingkat faktor pada sumbu x. Sebagai contoh:

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

ggplot dari dataset mobil dengan tingkat faktor yang ditentukan secara otomatis

# 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 dari dataset mobil dengan level faktor yang disusun ulang secara manual

Seperti yang ditunjukkan James dalam jawabannya, reorderadalah cara idiomatik untuk menyusun ulang tingkat faktor.

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

ggplot dari dataset mobil dengan tingkat faktor yang disusun ulang menggunakan fungsi penyusunan ulang

Richie Cotton
sumber
199

Cara terbaik bagi saya adalah menggunakan vektor dengan kategori yang saya butuhkan sebagai limitsparameter scale_x_discrete. Saya pikir ini adalah solusi yang cukup sederhana dan mudah.

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

masukkan deskripsi gambar di sini

Yuriy Petrovskiy
sumber
1
@HendyIrawan tidak ada legenda kecuali Anda memiliki dimensi lain (warna, isi) juga dipetakan ke variabel yang sama.
Gregor Thomas
5
Saya rasa ini adalah jawaban terbaik. Ini mengontrol urutan nilai sumbu x dan tidak mengubah atau memengaruhi bingkai data. Penggunaan factordan reorderperubahan karakteristik data, meskipun dalam ggplot()panggilan, dan begitu juga lebih dari yang diperlukan untuk masalah yang dihadapi.
mjandrews
2
Ini harus menjadi jawaban yang diterima !! Mengapa memperumit masalah dengan menulis 2 hingga 3 baris kode untuk sesuatu yang dapat Anda lakukan dalam satu baris kode yang elegan (standar)?
SilSur
1
Ini juga berhasil bagi saya untuk memesan x dengan nilai y: scale_x_discrete(limits = DT$x[order(-DT$y)])+
armipunk
39

Anda dapat menggunakan reorder:

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

Edit:

Untuk memiliki palang tertinggi di kiri, Anda harus menggunakan sedikit lumpur:

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

Saya berharap ini juga memiliki ketinggian negatif, tetapi ternyata tidak, jadi berhasil!

James
sumber
6
Saya terkejut jawaban ini tidak memiliki lebih banyak suara positif, 90% dari waktu ini adalah cara yang tepat untuk melakukannya.
Gregor Thomas
1
Saya pikir kedua faktor panggilan itu berlebihan. Ada panggilan implisit ke faktor untuk argumen pertama dan argumen kedua hte diasumsikan numerik.
IRTFM
Penjelasan yang membantu saya mengetahui apa yang dilakukan solusi ini di bawah tenda: rstudio-pubs-static.s3.amazonaws.com/…
keithpjolley
desc(reorder(.))dapat memberi Anda bilah tertinggi di sebelah kiri.
Jabro
31

Hadley telah mengembangkan sebuah paket bernama forcats. Paket ini membuat tugas jadi lebih mudah. Anda dapat memanfaatkan fct_infreq()saat Anda ingin mengubah urutan sumbu x dengan frekuensi faktor. Dalam kasus mtcarscontoh di posting ini, Anda ingin menyusun ulang tingkat cylberdasarkan frekuensi setiap tingkat. Level yang paling sering muncul tetap di sisi kiri. Yang Anda butuhkan hanyalah fct_infreq().

library(ggplot2)
library(forcats)

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

Jika Anda ingin sebaliknya, Anda dapat menggunakan fct_rev()bersama fct_infreq().

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

masukkan deskripsi gambar di sini

jazzurro.dll
sumber
2

Saya menyadari ini sudah lama, tetapi mungkin fungsi yang saya buat ini berguna untuk seseorang di luar sana:

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

Sekarang, dengan fungsi ini Anda dapat membuat plot secara interaktif dengan ggplot2, seperti ini:

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

Seperti yang bisa dilihat, order_axisfungsi membuat kerangka data lain dengan kolom baru bernama sama tetapi dengan a _odi akhir. Kolom baru ini memiliki level dalam urutan menaik, jadi ggplot2 secara otomatis memplot dalam urutan itu.

Ini agak terbatas (hanya berfungsi untuk karakter atau faktor dan kombinasi numerik kolom dan dalam urutan menaik) tetapi saya masih merasa sangat berguna untuk membuat plot saat bepergian.

eflores89
sumber
Saya kira saya tidak melihat keuntungan dari ini dibandingkan dengan hanya menggunakan reordersecara langsung. Tidakkah ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...melakukan hal yang sama, kira-kira secara ringkas, dan tanpa fungsi helper?
Gregor Thomas