ggplot2棒グラフのバーの順序付け


301

最大の棒が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つ、最後にストライカーが1つになるように、グラフを並べ替えます。ありがとう


12
ggplotはテーブル(またはデータフレーム)をいじる必要なしにそれらを並べ替えることができませんか?
tumultous_rooster 14年

1
@ MattO'Brienこれが単一の簡単なコマンドで実行されないことは信じられないことだと思います
Euler_Salter

@Zimanoあまりにも悪い私のコメントから得ているものです。私の観察はggplot2、OPではなくの作成者に対するものでした
Euler_Salter

2
@Euler_Salter明確にしていただき、ありがとうございます。元の発言を削除しました。
Zimano

回答:


214

順序付けの鍵は、必要な順序で因子のレベルを設定することです。順序付き因子は必要ありません。順序付けされた因子の追加情報は必要ありません。これらのデータが統計モデルで使用されている場合、誤ったパラメーター化が発生する可能性があります—多項式の対比は、このような名目上のデータには適切ではありません。

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

バープロット図

最も一般的な意味では、因子レベルを希望の順序に設定するだけです。指定しない場合、因子のレベルはアルファベット順にソートされます。上記のようにfactorへの呼び出し内でレベルの順序を指定することもでき、他の方法も可能です。

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

1
@Gavin:2つの簡略化:を既に使用withinしているためtheTable$Position、を使用する必要はなくsort(-table(...))、降順で実行できます。
Prasad Chalasani、2011年

2
@Prasad前者はテストの残り物だったので、指摘してくれてありがとう。後者については、コードの残りのすべてでに気付く-よりdecreasing = TRUEも意図を得る方がはるかに簡単であるため、使用するよりも逆のソートを明示的に求めることをお勧め-します。
ギャビンシンプソン

2
@GavinSimpson; に関する部分levels(theTable$Position) <- c(...)は、因子のレベルだけでなく、データフレームの実際のエントリが並べ替えられるという望ましくない動作につながると思います。この質問を参照してください。たぶん、それらの行を変更または削除する必要がありますか?
アントン

2
アントンに強く同意します。私はちょうどこの質問を見て、彼らが使用するために悪いアドバイスをどこで得たかについてあちこち調べましたlevels<-。その部分は少なくとも暫定的に編集します。
グレゴールトーマス

2
@Anton提案をありがとう(そして編集のためにGregorに); levels<-()今日はこれを決してしません。これは8年前のもので、当時の状況が変わっていたのか、それとも私がまったく間違っていたのかは思い出せませんが、それでも間違いであり、消去する必要があります。ありがとう!
Gavin Simpson

220

@GavinSimpson:これreorderは強力で効果的なソリューションです:

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

7
確かに+1であり、特にこの場合、数値的に活用できる論理的な順序があります。カテゴリの任意の順序を考慮し、アルファベット順にしたくない場合は、次のようにレベルを直接指定するのと同じくらい簡単(簡単?)です。
Gavin Simpson

2
これは最も卑劣です。元のデータフレームを変更する必要性をなくす
T.Fung

:ちょうどあなたが望むすべてがある場合は、長さ機能によって順番に、もう少しsuccinclyこれを行うことができますことに気づいたと昇順すると、私は頻繁にやりたい何かである、大丈夫ですラブリー、ggplot(theTable,aes(x=reorder(Position,Position,length))+geom_bar()
postylem

146

scale_x_discrete (limits = ...)バーの順序を指定するために使用します。

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

12
xをdata.frameの変数で表される任意の列としてプロットするようにプログラムしたいので、あなたのソリューションは私の状況に最も適しています。他の提案は、変数を含む式でxの次数の配置を表現するのが難しくなります。ありがとう!興味があれば、あなたの提案を使用して私のソリューションを共有できます。もう1つの問題、scale_x_discrete(limits = ...)を追加すると、グラフの右側に棒グラフと同じ幅の空白スペースがあることがわかりました。どうすれば空白を取り除くことができますか?それは何の目的も果たさないので。
Yu Shen

これは注文ヒストグラムの棒のために必要と思われる
geotheory

9
QIBIN:うわー...ここでの他の答えは機能しますが、あなたの答えははるかに簡潔でエレガントなだけでなく、ggplotのフレームワーク内から考えると最も明白なようです。ありがとうございました。
Dan Nguyen

私がこのソリューションを試したとき、私のデータでは、NAをグラフ化しませんでした。このソリューションを使用してNAをグラフ化する方法はありますか?
user2460499

これはエレガントでシンプルなソリューションです-ありがとうございます!!
Kalif Vaughn、

91

すでに提供されているソリューションは冗長すぎると思います。ggplotで周波数ソートされたバープロットを行うより簡潔な方法は、

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

これはAlex Brownが提案したものに似ていますが、少し短く、関数の定義がなくても機能します。

更新

私の古い解決策は当時は良かったと思いますが、最近forcats::fct_infreqでは頻度レベルで因子レベルをソートする方法を使用したいと思います。

require(forcats)

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

関数を並べ替える2番目の引数とそれが何をするのか理解できません。何が起こっているのか親切に説明していただけますか?
user3282777 2015

1
@ user3282777あなたはドキュメントstat.ethz.ch/R-manual/R-devel/library/stats/html/…を試しましたか?
Holger Brandl 2015

1
素晴らしい解決策!他の人が整然とした解決策を採用しているのを見るのは良いことです!
マイク

29

reorder()アレックスブラウンの回答と同様に、forcats::fct_reorder()。これは基本的に、指定された関数を適用した後、2番目の引数の値に従って、1番目の引数で指定された因子をソートします(デフォルト=中央値、これは因子レベルごとに1つの値しかないため、ここで使用します)。

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

ここに画像の説明を入力してください


1
forcatsとしての私見の最良のソリューションは、dplyrと同様に整頓されたパッケージです。
c0bra 2018

Zoalkeeperに賛成
otwtm

23

因子の単純な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

19

Position列を指定する必要があるの、レベルがカウントによって順序付けられる順序付けられた因子であるためです。

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

table(Position)Position列の頻度カウントを生成することに注意してください。)

次に、ggplot関数はカウントの降順でバーを表示します。geom_bar順序付けられた因子を明示的に作成する必要なしにこれを行うオプションがあるかどうかはわかりません。


私はあなたのコードを完全に解析しませんでしたが、reorder()統計ライブラリから同じタスクを実行すると確信しています。
追跡

@Chase reorder()この場合、どのように使用することを提案しますか?並べ替えが必要な要素は、それ自体の何らかの機能によって並べ替えられる必要があり、そのための良い方法を見つけるのに苦労しています。
Gavin Simpson

わかりました、with(theTable, reorder(Position, as.character(Position), function(x) sum(duplicated(x))))ある方法と別の方法ですwith(theTable, reorder(Position, as.character(Position), function(x) as.numeric(table(x))))が、これらは同じように複雑です...
ギャビンシンプソン

私は答えを使用するのsortではなく、少し単純化しましたorder
Prasad Chalasani

@Gavin-おそらく私はPrasadの元のコードを誤解しました(このマシンにはテストするRがありません...)が、彼は頻度に基づいてカテゴリを並べ替えているように見えましたreorder。この質問については、もっと複雑なものが必要であることに同意します。混乱させて申し訳ありません。
追跡

17

@HolgerBrandlで言及されているforcats :: fct_infreqに加えて、因子の順序を逆にする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の出力


"fct_infreq(Position)"は小さなことです。
ポール・

12

dplyr内でカウントすることが最善の解決策であることにザックは同意します。これが最も短いバージョンであることがわかりました:

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

これは、カウントがggplotまたはを使用しないでdplyrで行われるため、事前に因子レベルを並べ替えるよりも大幅に高速になりtableます。


12

以下のデータフレームのように、グラフの列が数値変数からのものである場合、より簡単なソリューションを使用できます。

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

このスレッドを見つけたとき、それが私が探していた答えでした。それが他の人に役立つことを願っています。


8

因子のレベルを並べ替えるために並べ替えを使用する別の方法。カウントに基づいて昇順(n)または降順(-n)。パッケージfct_reorderから使用するものと非常に似ていforcatsます:

降順

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

ここに画像の説明を入力してください

昇順

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

ここに画像の説明を入力してください

データフレーム:

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

2つの変数間の関係ではなく、1つの変数(「位置」)の分布のみを確認しているため、おそらくヒストグラムの方が適切なグラフになります。ggplotには、簡単にするgeom_histogram()があります。

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

ここに画像の説明を入力してください

geom_histogram()の使用:

私は考える(geom_histogramをそれは異なり連続と離散データを扱うよう)が少し風変わりです。

以下のために連続したデータは、あなただけ使用することができますgeom_histogramを()パラメータなしで。たとえば、数値ベクトル「スコア」を追加すると...

    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

そして、「Score」変数でgeom_histogram()を使用します...

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

ここに画像の説明を入力してください

離散データ「位置」のように、私たちは使用して、バーの高さyの値を与える美的によって計算された計算された統計を指定する必要がありますstat = "count"

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

注:不思議なことに、混乱を招くようにstat = "count"、継続的なデータにも使用できます。これにより、美的に満足できるグラフが得られると思います。

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

ここに画像の説明を入力してください

編集DebanjanBの有用な提案に応じた拡張回答。


0

ggplot2このための「自動」ソリューションを提供していないことは非常に迷惑であることがわかりました。それが私がでbar_chart()関数を作成した理由ggchartsです。

ggcharts::bar_chart(theTable, Position)

ここに画像の説明を入力してください

デフォルトでbar_chart()は、バーを並べ替えて水平プロットを表示します。そのセットを変更するには horizontal = FALSE。さらにbar_chart()、バーと軸の間の見苦しい「ギャップ」を削除します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.