Ggplot2 çubuk grafikteki çubukları sipariş et


301

En büyük çubuğun y eksenine en yakın ve en kısa çubuğun en uzak olacağı bir çubuk grafik yapmaya çalışıyorum. Yani bu benim tablom gibi

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

Bu yüzden pozisyona göre oyuncu sayısını gösteren bir çubuk grafik oluşturmaya çalışıyorum

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

ancak grafikte önce kaleci çubuğu sonra savunmayı ve son olarak forvetini gösterir. Grafiğin, savunma çubuğunun y eksenine, kaleciye ve son olarak forvete en yakın olacağı şekilde sıralanmasını istiyorum. Teşekkürler


12
ggplot, tablo (veya veri çerçevesi) ile uğraşmak zorunda kalmadan bunları sizin için yeniden sıralayamıyor mu?
tumultous_rooster

1
@ MattO'Brien Bunun tek ve basit bir komutla yapılmamasını inanılmaz buluyorum
Euler_Salter

@Zimano Yorumumdan aldığınız şey çok kötü. ggplot2
Gözlemim

2
@Euler_Salter Açıklamak için teşekkür ederim, sana böyle attığım için içten özür dilerim. Orijinal sözümü sildim.
Zimano

Yanıtlar:


214

Sıralamanın anahtarı, faktörün seviyelerini istediğiniz sıraya göre ayarlamaktır. Sıralı bir faktör gerekli değildir; sıralı bir faktördeki ekstra bilgi gerekli değildir ve bu veriler herhangi bir istatistiksel modelde kullanılıyorsa, yanlış parametreleme meydana gelebilir - polinom kontrastları böyle nominal veriler için doğru değildir.

## 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 figürü

En genel anlamda, faktör düzeylerini istenen sırada olacak şekilde ayarlamamız yeterlidir. Belirtilmezse, bir faktörün düzeyleri alfabetik olarak sıralanacaktır. Faktör çağrısı içinde seviye sırasını yukarıdaki gibi belirtebilirsiniz ve başka yollar da mümkündür.

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

1
@Gavin: 2 basitleştirme: zaten kullandığınızdan within, kullanmaya gerek yoktur theTable$Positionve sadece sort(-table(...))siparişi azaltmak için yapabilirsiniz.
Prasad Chalasani

2
@Prasad, testten kalan bir şeydi, bu yüzden işaret ettiğiniz için teşekkürler. Ikincisi kadarıyla, açıkça kodun geri kalanında fark daha çok -niyeti elde etmek daha kolay olduğu gibi kullandığınız daha ters sıralama istiyor . decreasing = TRUE-
Gavin Simpson

2
@GavinSimpson; Bence ilgili bölüm levels(theTable$Position) <- c(...), veri faktörünün gerçek girişlerinin yeniden sıralandığı ve sadece faktör seviyelerinin değil, istenmeyen davranışlara yol açtığını düşünüyorum . Bu soruya bakın . Belki bu satırları değiştirmeniz veya kaldırmanız gerekir?
Anton

2
Anton ile kesinlikle katılıyorum. Ben sadece bu soruyu gördüm ve nerede kullanmak için kötü tavsiye aldık poking gitti levels<-. Bu kısmı en azından geçici olarak düzenleyeceğim.
Gregor Thomas

2
@Anton Öneri için teşekkürler (ve düzenleme için Gregor'a); Bunu asla levels<-()bugün yapmam . Bu 8 yıl öncesinden bir şey ve o zamanlar farklı olup olmadığını ya da sadece yanlış olup olmadığımı hatırlayamıyorum, ama ne olursa olsun, yanlış ve silinmesi gerekiyor! Teşekkürler!
Gavin Simpson

220

@GavinSimpson: reorderbunun için güçlü ve etkili bir çözümdür:

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

7
Gerçekten +1 ve özellikle bu durumda sayısal olarak yararlanabileceğimiz mantıklı bir düzen var. Kategorilerin rastgele sıralanmasını göz önünde bulundurursak ve alfabetik istemiyorsak, seviyeleri doğrudan gösterildiği gibi belirtmek o kadar kolay (kolay?).
Gavin Simpson

2
Bu en güzel. Orijinal veri çerçevesini değiştirme ihtiyacını ortadan kaldırın
T.Fung

Güzel, sadece bunu biraz daha özlü bir şekilde yapabileceğinizi fark ettiniz, eğer istediğiniz tek şey uzunluk fonksiyonu ile sipariş vermek ve artan sipariş ggplot(theTable,aes(x=reorder(Position,Position,length))+geom_bar()
tamamsa

146

scale_x_discrete (limits = ...)Çubukların sırasını belirtmek için kullanılır .

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

12
Çözümüm, durumum için en uygun olanıdır, çünkü x'in bir data.frame içindeki bir değişken tarafından ifade edilen rastgele bir sütun olmasıyla çizim yapmak istiyorum. Diğer öneriler, değişkenin dahil olduğu bir ifade ile x sırasının düzenlenmesini ifade etmek daha zor olacaktır. Teşekkürler! İlgi varsa, önerinizi kullanarak çözümümü paylaşabilirim. Sadece bir sorun daha, scale_x_discrete (sınırlar = ...) ekleyerek, grafiğin sağında, çubuk grafik kadar geniş bir boşluk olduğunu buldum. Boş alandan nasıl kurtulabilirim? Herhangi bir amaca hizmet etmediği için.
Yu Shen

Bu histogram çubukları sipariş etmek için gerekli görünüyor
jeoloji

9
QIBIN: Vay canına ... buradaki diğer cevaplar işe yarıyor, ancak cevabınız sadece en özlü ve zarif değil, aynı zamanda ggplot'un çerçevesinden düşünürken en açık görünüyor. Teşekkür ederim.
Dan Nguyen

Bu çözümü denediğimde, verilerimde NA'ları çizmedi. Bu çözümü kullanmanın ve NA'ların grafiğini çizmenin bir yolu var mı?
user2460499

Bu zarif ve basit bir çözüm - teşekkür ederim !!
Kalif Vaughn

91

Zaten sağlanan çözümlerin aşırı ayrıntılı olduğunu düşünüyorum. Ggplot ile frekans sıralı bir barplot yapmanın daha kısa bir yolu

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

Alex Brown'un önerdiğine benzer, ancak biraz daha kısa ve anonim bir işlev tanımı olmadan çalışır.

Güncelleme

Eski çözümümün o zaman iyi olduğunu düşünüyorum, ancak günümüzde forcats::fct_infreqfaktör seviyelerini frekansa göre sıralamayı tercih ediyorum :

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()

Fonksiyonu yeniden sıralamak için ikinci argümanı ve ne işe yaradığını anlamıyorum. Neler olduğunu lütfen açıklayabilir misiniz?
user3282777

1
@ user3282777 stat.ethz.ch/R-manual/R-devel/library/stats/html/… belgelerini denediniz mi?
Holger Brandl

1
Harika bir çözüm! Diğerlerinin düzenli çözümler kullandığını görmek güzel!
Mike

29

Gibi reorder()Alex Brown'un yanıtında, biz de kullanabiliriz forcats::fct_reorder(). Temel olarak, belirli bir işlevi uyguladıktan sonra 2. bağımsız değişkendeki değerlere göre 1. bağımsız değişkende belirtilen faktörleri sıralar (varsayılan = medyan, burada kullandığımız faktör düzeyi başına sadece bir değer vardır).

OP sorusunda, gerekli sıranın alfabetik olduğu için faktörler oluşturduğunuzda varsayılan sıralama düzeni olduğu için bir utançtır, bu nedenle bu işlevin gerçekte ne yaptığını gizleyecektir. Daha açık bir ifade için, "Kaleci" nin yerine "Zoalkeeper" yazacağım.

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

resim açıklamasını buraya girin


1
Forcats olarak IMHO en iyi çözümü aynı zamanda düzenli bir paket dplyr.
c0bra

başparmak yukarıya için Zoalkeeper
otwtm

23

Basit bir dplyr tabanlı faktörlerin yeniden sıralanması bu sorunu çözebilir:

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

19

PositionSütunu , düzeylerin sayılarına göre sıralandığı sıralı bir faktör olarak belirtmeniz gerekir :

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

( Sütunun table(Position)bir frekans sayımı ürettiğini unutmayın Position.)

Ardından ggplotişleviniz çubukları azalan sırayla gösterecektir. geom_barAçıkça sıralı bir faktör oluşturmak zorunda kalmadan bunu yapmak için bir seçenek olup olmadığını bilmiyorum .


Kodunuzu orada tam olarak ayrıştırmadım, ancak reorder()istatistik kütüphanesinden aynı görevi yerine getirdiğinden eminim .
Chase

@Chase reorder()bu durumda nasıl kullanmayı öneriyorsunuz ? Yeniden sıralamayı gerektiren faktörün kendi işlevi tarafından yeniden sıralanması gerekir ve bunu yapmanın iyi bir yolunu görmek için mücadele ediyorum.
Gavin Simpson

tamam, with(theTable, reorder(Position, as.character(Position), function(x) sum(duplicated(x))))bir yolu var, diğeri with(theTable, reorder(Position, as.character(Position), function(x) as.numeric(table(x))))ama bunlar aynı derecede kıvrımlı ...
Gavin Simpson

Cevabı kullanmak sortyerine biraz sadeleştirdimorder
Prasad Chalasani

@Gavin - belki de Prasad'ın orijinal kodunu yanlış anladım (test etmek için bu makinede R yok ...) ama kategorileri sık sık görebilmiyormuş gibi görünüyordu, ki bu reorderda yapmaya uygun. Bu soruya daha fazla dahil olan bir şeyin gerekli olduğunu kabul ediyorum. Karışıklık için özür dilerim.
Chase

17

@HolgerBrandl tarafından belirtilen forcats :: fct_infreq'e ek olarak, faktör sırasını tersine çeviren forcats :: fct_rev vardır.

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 çıkışı


"fct_infreq (Pozisyon)" çok şey yapar küçük şey, teşekkürler !!
Paul

12

Ben dplyr içinde saymanın en iyi çözüm olduğunu zach ile aynı fikirdeyim. Bunu en kısa versiyon olarak buldum:

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

Sayım ggplot'ta veya kullanımda değil dplyr'de yapıldığından, bu, faktör düzeylerini önceden yeniden sıralamaktan önemli ölçüde daha hızlı olacaktır table.


12

Grafik sütunları aşağıdaki veri çerçevesinde olduğu gibi sayısal bir değişkenden geliyorsa, daha basit bir çözüm kullanabilirsiniz:

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

Sıralama değişkeninden önceki eksi işareti (-Qty) sıralama yönünü kontrol eder (artan / azalan)

Test için bazı veriler:

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

Bu konuyu bulduğumda aradığım cevap buydu. Umarım başkaları için yararlıdır.


8

Bir faktörün seviyelerini sıralamak için yeniden sıralamayı kullanan başka bir alternatif . Sayıya göre artan (n) veya azalan sırada (-n). Kullanarak birine çok benzer fct_reordergelen forcatspaketin:

Azalan sipariş

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

resim açıklamasını buraya girin

Artan düzen

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

resim açıklamasını buraya girin

Veri çerçevesi:

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

5

Sadece bir dağılımına aradığımızdan tek bir değişken ilişkisine bakarak karşı ( "pozisyon") iki değişken , belki de bir histogramı daha uygun grafik olacaktır. ggplot, geom_histogram () yöntemini kolaylaştırır:

ggplot(theTable, aes(x = Position)) + geom_histogram(stat="count")

resim açıklamasını buraya girin

Geom_histogram () kullanma:

Sürekli ve ayrık verileri farklı şekilde ele aldığı için geom_histogram ( ) biraz tuhaf olduğunu düşünüyorum .

İçin sürekli veri , sadece kullanabilirsiniz geom_histogram () hiçbir parametrelerle. Örneğin, sayısal bir "Skor" vektörü eklersek ...

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

ve "Score" değişkeninde geom_histogram () kullanın ...

ggplot(theTable, aes(x = Score)) + geom_histogram()

resim açıklamasını buraya girin

İçin ayrı veri "pozisyon" gibi kullandığımız bar yüksekliği için y değerini vermek üzere estetik hesaplanan hesaplanan istatistik belirtmek gerekir stat = "count":

 ggplot(theTable, aes(x = Position)) + geom_histogram(stat = "count")

Not: Meraklı ve kafa karıştırıcı bir şekilde stat = "count"sürekli veriler için de kullanabilirsiniz ve bence daha estetik açıdan hoş bir grafik sağlıyor.

ggplot(theTable, aes(x = Score)) + geom_histogram(stat = "count")

resim açıklamasını buraya girin

Düzenlemeler : DebanjanB'in yararlı önerilerine yanıt olarak genişletilmiş yanıt .


0

Bunun ggplot2için 'otomatik' bir çözüm sunmayan çok can sıkıcı buldum . Bu yüzden bar_chart()içinde fonksiyonu yarattım ggcharts.

ggcharts::bar_chart(theTable, Position)

resim açıklamasını buraya girin

Varsayılan bar_chart()olarak çubukları sıralar ve yatay bir grafik görüntüler. Bu seti değiştirmek için horizontal = FALSE. Ek olarak, bar_chart()çubuklar ve eksen arasındaki çirkin 'boşluğu' kaldırır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.