2014-10-07 112 views
10

我試圖在facet-wrapped圖中使用reorder,該圖也在ggplot2中使用scales = free_x,但重新排序函數沒有正確地重新排序x軸。以下是我正在運行的是什麼:R:使用ggplot2中的free_x對facet_wrapped x軸重新排序

library(ggplot2) 

df <- read.table("speaking_distribution_by_play.txt", 
       header = F, 
       sep = "\t") 

ggplot(df, aes(x=reorder(V2, V3), y=V3)) + 
    geom_bar(stat = "identity") + 
    facet_wrap(~V1, ncol = 4, scales = "free_x") + 
    opts(title = "Distribution of Speakers in Shakespearean Drama") + 
    xlab("Speaking Role") + 
    ylab("Words Spoken") + 
    opts(axis.text.x=theme_text(angle=90, hjust=1)) 

運行從this tab-separated file讀取數據幀上的代碼產生在每個方位圖的x軸僅部分有序的圖。 Someone else on SO問了一個非常類似的問題,但唯一建議的解決方案是使用網格排列。因爲我的數據集比那個問題中的數據集大得多,但是這不會是一個非常快速的操作,所以我想問一下:有沒有辦法重新排列每個分面圖的x軸的順序,以增加(或減少)大小順序顯示條形?我非常感謝他人在這個問題上提供的任何幫助。

+1

哇...'opts'已經廢棄了,因爲2012年我認爲這是你更新你的'ggplot2'包的時間。你的第一個帶標題的'opts()'然後可以用'labs()'替換(你的'xlab'和'ylab'可以進去),你的第二個'opts'將被'theme() '。格雷戈爾謝謝, – Gregor 2014-10-07 14:48:56

+0

謝謝!任何關於重新排序問題的想法? – duhaime 2014-10-07 14:51:56

+1

如果你想在不同方面有不同的訂單,我認爲'grid.arrange'是你最好的選擇。 – Gregor 2014-10-07 15:26:20

回答

6

問題是,ggplotV2視爲單因子;它不是每個方面的子集V2(值爲V1),然後將其中的每一個視爲獨立因素(不幸)。由於某些角色(「信使1」等)出現在多個角色中,因此這些級別根據角色在遇到的第一個角色中的重要性排序。

有一個解決方法,但它有點瑕疵:你需要通過將播放名稱連接到每個角色來使角色唯一,然後使用它作爲x值。要恢復原始角色,請關閉軸文本,並使用geom_text(...)作爲條形標籤。這裏有一個例子:

gg  <- df[order(df$V1,-df$V3),] # reorder by play and lines 
gg$lvl <- with(df,paste(V2,V1,sep=".")) 

ggplot(gg[gg$V1 %in% unique(df$V1)[1:4],], 
     aes(x=factor(lvl,levels=unique(lvl)), y=V3)) + 
    geom_text(aes(y=5,label=V2),angle=90,size=3,hjust=-0)+ 
    geom_bar(stat = "identity", fill="blue",alpha=0.2) + 
    facet_wrap(~V1, ncol = 2, scales="free_x") + 
    labs(title="Distribution of Speakers in Shakespearean Drama", 
     x="Speaking Role", y="Words Spoken") + 
    theme(axis.text.x=element_blank(),axis.ticks.x=element_blank()) 

這看起來在這樣一個小規模的可怕的(不是那麼糟糕,因爲你原來的情節,雖然...)。但是如果你把它做得更大(因爲你需要做38次,沒有??),那麼你可以看到標籤和酒吧。如果你真的想下面條的標籤,使用這樣的:

ggplot(gg[gg$V1 %in% unique(df$V1)[1:4],], 
     aes(x=factor(lvl,levels=unique(lvl)), y=V3)) + 
    geom_text(aes(y=-5,label=V2),angle=90,size=3,hjust=1)+ 
    ylim(-500,NA)+ 
    geom_bar(stat = "identity", fill="lightblue") + 
    facet_wrap(~V1, ncol = 2, scales="free_x") + 
    labs(title="Distribution of Speakers in Shakespearean Drama", 
     x="Speaking Role", y="Words Spoken") + 
    theme(axis.text.x=element_blank(),axis.ticks.x=element_blank()) 

再次,看起來可怕在這個規模不大,但更好的擴大。無論哪種方式,您可能需要調整geom_text(...)中的size=...參數。

+1

聰明的黑客!熱情+1 – Gregor 2014-10-07 18:46:46

+0

你是一位學者,@ jlhoward!非常感謝這個聰明的解決方法:) – duhaime 2014-10-07 20:45:59

9

使用稍有不同的方法,可以將標籤保留在圖表下面的區域中。此版本通過以類似於jlhoward方法的方式連接V1和V2來創建獨特的x中斷,但是隨後使用scale_x_discrete語句中下面的代碼中的函數角色將V2還原爲x標籤。

library(ggplot2) 
df <- read.table("speaking_distribution_by_play.txt", 
      header = F, 
      sep = "\t") 

# Creates a small test subset; remove for complete set 
df <- df[df$V1 %in% c("Mac.xml","MM.xml","MND.xml","MV.xml"),] 

# used to create x-axis label restoring original name of role 
roles <- function(x) sub("[^_]*_","",x) 

ggplot(cbind(df, V4=paste(df$V1,df$V2,sep="_")), aes(x=reorder(V4,V3), y=V3)) + 
geom_bar(stat = "identity") + 
facet_wrap(~ V1, ncol=4, scales = "free_x") + 
labs(title = "Distribution of Speakers in Shakespearean Drama") + 
xlab("Speaking Role") + 
ylab("Words Spoken") + 
scale_x_discrete(labels=roles) + 
theme(axis.text.x=element_text(angle=90, hjust=1)) 

enter image description here

+0

這真是太棒了@WaltS!多麼簡單的修復!謝謝:) – duhaime 2014-10-08 02:08:43

+2

很高興幫助你。我注意到我需要對角色函數進行一些小修改,以正確處理V1的所有值。上面編輯的版本有這個修復程序。對於那個很抱歉。 – WaltS 2014-10-08 14:56:32

+0

我希望我可以兩次對這個遊戲讚不絕口。這只是爲我節省了幾個小時掙扎的事情。 – 2017-01-22 18:47:42