2014-10-07 17 views
10

Tôi đang cố sử dụng reorder trong cốt truyện được thêm vào khuôn mặt cũng sử dụng scales = free_x trong ggplot2, nhưng chức năng sắp xếp lại không sắp xếp lại trục x đúng cách. Dưới đây là những gì tôi đang chạy:R: Sắp xếp lại trục x đã được cắt xén với free_x trong ggplot2

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

Chạy mã vào khung dữ liệu đọc từ this tab-separated file mang lại một âm mưu trong đó trục x của từng lô mặt được lệnh chỉ một phần. Someone else on SO hỏi một câu hỏi rất giống nhau, nhưng giải pháp được đề xuất duy nhất là sử dụng sắp xếp lưới. Do tập dữ liệu của tôi lớn hơn một chút so với tập dữ liệu trong câu hỏi đó, tuy nhiên, đây không phải là một thao tác nhanh chóng khủng khiếp, vì vậy tôi muốn hỏi: Có cách nào để sắp xếp lại trục x của mỗi ô mặt để hiển thị các thanh theo thứ tự tăng (hoặc giảm) kích thước? Tôi sẽ rất biết ơn vì bất kỳ sự giúp đỡ nào mà người khác có thể đưa ra về câu hỏi này.

+1

Whoa ... 'opts' đã bị phản đối kể từ năm 2012. Tôi nghĩ đã đến lúc bạn cập nhật 'gói ggplot2' của bạn. 'Opts()' đầu tiên của bạn với tiêu đề có thể được thay thế bằng 'labs()' (và 'xlab' và' ylab' của bạn có thể đi vào bên trong), và 'opts' thứ hai của bạn sẽ được thay thế bởi' chủ đề() '. – Gregor

+0

Cảm ơn, Gregor! Bất kỳ suy nghĩ về câu hỏi sắp xếp lại? – duhaime

+1

Nếu bạn muốn các đơn đặt hàng khác nhau trong các khía cạnh khác nhau, tôi nghĩ rằng 'grid.arrange' là đặt cược tốt nhất của bạn. – Gregor

Trả lời

6

Vấn đề là ggplot xử lý V2 là một yếu tố đơn ; nó không tập hợp con số V2 cho mỗi khía cạnh (giá trị V1) và sau đó xử lý từng yếu tố đó như là các yếu tố độc lập (không may). Vì một số vai trò ("Messenger 1", vv), xuất hiện trong nhiều lần phát, các cấp đó được sắp xếp dựa trên tầm quan trọng của chúng trong lần phát đầu tiên mà chúng gặp phải.

Có một cách giải quyết khác, nhưng đó là một chút hack: bạn cần phải tạo vai trò duy nhất bằng cách nối tên của trò chơi cho mỗi trò chơi, sau đó sử dụng giá trị đó làm giá trị x. Để lấy lại vai trò ban đầu, hãy tắt văn bản trục và thay vào đó hãy sử dụng geom_text(...) cho nhãn thanh. Dưới đây là một ví dụ:

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

này trông khủng khiếp ở quy mô nhỏ như vậy (không xấu như cốt truyện ban đầu của bạn, mặc dù ...). Nhưng nếu bạn làm cho nó lớn hơn (như bạn sẽ phải làm với 38 lượt, không ??), sau đó bạn có thể thấy các nhãn và các thanh. Nếu bạn thực sự muốn các nhãn dưới đây các quán bar, sử dụng một cái gì đó như thế này:

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

Một lần nữa, trông khủng khiếp ở quy mô nhỏ này, nhưng mở rộng tốt hơn. Dù bằng cách nào bạn cũng có thể cần phải chỉnh sửa thông số size=... trong geom_text(...).

+1

Thông minh hack! Nhiệt tình +1 – Gregor

+0

Bạn là một học giả, @jlhoward! Rất cám ơn vì cách giải quyết thông minh này :) – duhaime

9

Với cách tiếp cận hơi khác, bạn có thể giữ các nhãn trong khu vực bên dưới biểu đồ. Phiên bản này tạo ra các ngắt x duy nhất bằng cách ghép nối V1 và V2 theo cách tương tự với phương thức của jlhoward nhưng sau đó khôi phục V2 dưới dạng các nhãn x bằng cách sử dụng các vai trò chức năng trong mã bên dưới trong câu lệnh scale_x_discrete.

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

Điều này thật tuyệt vời, @WaltS! Thật là một sửa chữa đơn giản!Cảm ơn bạn :) – duhaime

+2

Vui vì nó đã giúp bạn. Tôi nhận thấy rằng tôi cần phải thực hiện một thay đổi nhỏ cho vai trò chức năng để xử lý đúng tất cả các giá trị của V1. Phiên bản đã chỉnh sửa ở trên có bản sửa lỗi này. Xin lỗi vì điều đó. – WaltS

+0

Tôi ước tôi có thể upvote cái này hai lần. Điều này vừa tiết kiệm cho tôi về một cái gì đó tôi đã đấu tranh với hàng giờ. –

Các vấn đề liên quan