2015-11-04 39 views
0

使用stack='identity'繪製堆積條形圖時,我注意到堆棧的順序在每個條形圖中以不同的方式顯示。這是使用stat='bin'的情節,就是ggplot計算每個類別的飛行元素數作圖之前(data.table是有更高版本):如何使用stat ='identity'來保持ggplot中堆棧的順序?

library(ggplot2) 
library(data.table) 

diamonds <- data.table(diamonds) 

ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar(position="fill") 

enter image description here

在每個酒吧,訂單'cut'的順序依次是因素的順序。不過,如果我繪製之前總結,並使用stat=identity,這個訂單丟失:

diamonds_sum <- diamonds[, list(.N), by=list(cut, clarity)] 
ggplot(diamonds_sum, aes(clarity, y=N, fill = cut)) + geom_bar(stat="identity", position="fill") 

enter image description here

出現這種情況,儘管兩個表中級別的順序是一樣的:

levels(diamonds_sum$cut) == levels(diamonds$cut) 
[1] TRUE TRUE TRUE TRUE TRUE 

所以這個問題是雙重的:(i)爲什麼堆棧的順序不一樣?和(ii)如何解決這個問題?

這個簡單的解決方案當然是一直使用stat='bin',但是我的真實數據集有幾百萬條記錄,總結和繪圖速度更快。

回答

2

的原因是訂單彙總後得到的新data.table混合起來,ggplot2取行作爲輸入的順序。從下面的兩種方法進行比較,例如輸出(只顯示前10行,因爲它們說明了差異不夠好):

> diamonds[, .N, by=.(cut, clarity)] 
      cut clarity N 
1:  Ideal  SI2 2598 
2: Premium  SI1 3575 
3:  Good  VS1 648 
4: Premium  VS2 3357 
5:  Good  SI2 1081 
6: Very Good VVS2 1235 
7: Very Good VVS1 789 
8: Very Good  SI1 3240 
9:  Fair  VS2 261 
10: Very Good  VS1 1775 

> diamonds[, .N, by=.(cut, clarity)][order(clarity,cut)] 
      cut clarity N 
1:  Fair  I1 210 
2:  Good  I1 96 
3: Very Good  I1 84 
4: Premium  I1 205 
5:  Ideal  I1 146 
6:  Fair  SI2 466 
7:  Good  SI2 1081 
8: Very Good  SI2 2100 
9: Premium  SI2 2949 
10:  Ideal  SI2 2598 

正如你所看到的,你原來的代碼將導致混亂的行,而第二種方法導致排序行。所以,當你這樣做:

diamonds_sum <- diamonds[, .N, by=.(cut, clarity)][order(clarity,cut)] 

,然後繪製有:

ggplot(diamonds_sum, aes(clarity, y=N, fill = cut)) + 
    geom_bar(stat="identity", position="fill") 

你得到期望的結果:

enter image description here


而且dplyr會給你同樣的行爲。您將需要arrange以獲得正確的訂單。比較以下兩個輸出:

diamonds %>% group_by(cut, clarity) %>% tally() 
diamonds %>% group_by(cut, clarity) %>% tally() %>% arrange(clarity,cut) 

與基礎R總結並不會導致您所描述的問題。當你這樣做:

diamonds_sum <- aggregate(diamonds[,"cut",with=FALSE], list(diamonds$cut,diamonds$clarity), length) 

,然後用情節:

ggplot(diamonds_sum, aes(Group.2, y=cut, fill = Group.1)) + 
    geom_bar(stat="identity", position="fill") 

你得到正確的結果:

enter image description here

+0

非常好,謝謝!我錯誤地認爲ggplot並不關心行中元素的順序,只關心繪製元素的順序。活到老,學到老。 – fridaymeetssunday

+0

@fridaymeetssunday呃,我其實也有這種印象。你的榜樣讓我意識到它確實很重要。 – Jaap