2013-08-16 31 views
14

Tôi muốn âm mưu hai biến trên một cốt truyện tương tự như một quần thể kim tự tháp tương tự như sau:Hai biểu đồ thanh ngang với trục được chia sẻ trong ggplot2 (tương tự như kim tự tháp dân số)

plot

âm mưu này là gần ở đó nhưng không hoàn toàn, vì những lý do tôi sẽ liệt kê bên dưới.

tôi sản xuất âm mưu này với đoạn mã sau:

DATA <- data.frame(
    state = c("AK", "TX", "CA", "MT", "NM", "AZ", "NV", "CO", "OR", "WY", "MI", "MN", "UT", "ID", "KS", "NE", "SD", "WA", "ND", "OK"), 
    sales_staff = c(20,30,40,10,15,35,18,25,22,7,12,22,3,4,5,8,14,28,24,32) 
) 

set.seed(1) 
DATA$sales <- DATA$sales_staff * 50 + (runif(nrow(DATA)) * 1000) 

# Order the state factor by number of sales staff so that it is plotted in that order 
DATA$state <- factor(DATA$state, levels = DATA[order(DATA$sales_staff),"state"]) 

Tôi muốn "keo" hai lô back-to-back, vì vậy tôi sử dụng multiplot() chức năng đúng nguyên văn từ http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_%28ggplot2%29/

(tôi sẽ không tái tạo các mã cho chức năng đó ở đây cho ngắn gọn và rõ ràng)

mã của tôi cho cốt truyện cuối cùng là:

library(ggplot2) 

g1 <- ggplot(data = DATA, aes(x = state, y = sales_staff)) + 
    geom_bar(stat = "identity") + ggtitle("Number of sales staff") + 
    theme(axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank(), plot.margin = unit(c(1,0,1,0), "mm")) + 
    scale_y_reverse() + coord_flip() 

g2 <- ggplot(data = DATA, aes(x = state, y = sales)) + 
    geom_bar(stat = "identity") + ggtitle("Sales (x $1000)") + 
    theme(axis.title.x = element_blank(), axis.title.y = element_blank(), plot.margin = unit(c(1,5,1,0), "mm")) + 
    coord_flip() 

multiplot(g1, g2, cols = 2) 

OK. Vì vậy, có gì sai với cốt truyện này?

  • Tôi cần có dấu tick ở trục bên phải của ô bên trái. Tôi không thể tìm ra cách để làm điều đó.
  • Hai ô có chiều rộng khác nhau. Điều này là do các trạng thái nằm ở giữa là các nhãn trục từ ô bên phải và sử dụng một số khoảng trống cho ô đó.

Tôi đã đạt một bức tường gạch để đưa âm mưu này đến "chất lượng sản xuất". Tôi bắt đầu tự hỏi nếu tôi đang đi về điều này một cách sai lầm bởi vì tôi nghĩ bước tiếp theo sẽ là vẽ các nhãn trục như một cột thứ ba riêng biệt giữa hai lô. (Tôi chưa biết cách làm điều này). Điều này sẽ giải quyết vấn đề "kích thước bằng nhau" và cho phép tôi thêm tiêu đề "trạng thái", vì vậy nó vẫn có thể là cách để đi. Nhưng tôi không thể không tự hỏi nếu có một cách đơn giản hơn ...

Bất kỳ lời khuyên hoặc hỗ trợ nào được đánh giá cao!

+1

Bạn có thể điều chỉnh http://stackoverflow.com/questions/14680075/simpler-population-pyramid-in-ggplot2?lq=1 cho mục đích của bạn? – mnel

+2

Tôi là một fan hâm mộ 'ggplot2' chết người và sử dụng gói cho tất cả mọi thứ tôi có thể, nhưng khi tôi cần tạo một biểu đồ kim tự tháp tương tự như trên một vài tháng, tôi cuối cùng đã từ bỏ và sử dụng 'pyramid.plot' từ gói 'plotrix'. Không, tôi không thích cú pháp, nhưng nó không khó và tôi có kết quả tốt hơn so với 'ggplot2' và ít bị rối tung hơn. – SlowLearner

+0

Bạn nên tìm kiếm "back to back charts". –

Trả lời

22

Đây là giải pháp rất dài cho cốt truyện của bạn. Ý tưởng là tạo ra cốt truyện mới chỉ chứa các tên tiểu bang và ve trên cả hai mặt và sau đó sử dụng nó làm cốt truyện ở giữa.

Đối với ô này, tôi đã thêm tiêu đề không có tên để nhận khoảng trống và ylab(NULL) để xóa không gian. Đối với các giá trị lề trái và phải là -1 để có được lô gần hơn với các ô khác. Thư viện grid phải được thêm trước khi âm mưu sử dụng hàm unit() cho lợi nhuận lô.

library(grid) 
g.mid<-ggplot(DATA,aes(x=1,y=state))+geom_text(aes(label=state))+ 
    geom_segment(aes(x=0.94,xend=0.96,yend=state))+ 
    geom_segment(aes(x=1.04,xend=1.065,yend=state))+ 
    ggtitle("")+ 
    ylab(NULL)+ 
    scale_x_continuous(expand=c(0,0),limits=c(0.94,1.065))+ 
    theme(axis.title=element_blank(), 
     panel.grid=element_blank(), 
     axis.text.y=element_blank(), 
     axis.ticks.y=element_blank(), 
     panel.background=element_blank(), 
     axis.text.x=element_text(color=NA), 
     axis.ticks.x=element_line(color=NA), 
     plot.margin = unit(c(1,-1,1,-1), "mm")) 

Cả hai ô gốc đều được sửa đổi. Đầu tiên, loại bỏ trục y cho ô thứ hai và cũng làm lề trái/lề phải -1.

g1 <- ggplot(data = DATA, aes(x = state, y = sales_staff)) + 
    geom_bar(stat = "identity") + ggtitle("Number of sales staff") + 
    theme(axis.title.x = element_blank(), 
     axis.title.y = element_blank(), 
     axis.text.y = element_blank(), 
     axis.ticks.y = element_blank(), 
     plot.margin = unit(c(1,-1,1,0), "mm")) + 
    scale_y_reverse() + coord_flip() 

g2 <- ggplot(data = DATA, aes(x = state, y = sales)) +xlab(NULL)+ 
    geom_bar(stat = "identity") + ggtitle("Sales (x $1000)") + 
    theme(axis.title.x = element_blank(), axis.title.y = element_blank(), 
     axis.text.y = element_blank(), axis.ticks.y = element_blank(), 
     plot.margin = unit(c(1,0,1,-1), "mm")) + 
    coord_flip() 

Bây giờ hãy sử dụng thư viện gridExtra và chức năng d grid.arrange() để ghép các ô. Trước khi vẽ đồ thị, tất cả các ô được làm thành các rãnh.

library(gridExtra) 
gg1 <- ggplot_gtable(ggplot_build(g1)) 
gg2 <- ggplot_gtable(ggplot_build(g2)) 
gg.mid <- ggplot_gtable(ggplot_build(g.mid)) 

grid.arrange(gg1,gg.mid,gg2,ncol=3,widths=c(4/9,1/9,4/9)) 

enter image description here

+2

+1 cho một lượng lớn các nỗ lực! Và rõ ràng là để trả lời OP –

+0

Một cái gì đó tương tự đã được đề xuất bởi Prasad http://stackoverflow.com/questions/4559229/drawing-pyramid-plot-using-r-and-ggplot2 –

+0

@ RomanLuštrik Nó seams như vậy nhưng tôi đã không thấy rằng trước khi :) –

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