2013-04-05 45 views
13

Tôi đang cố gắng thêm bảng dữ liệu vào biểu đồ được tạo bằng ggplot (tương tự như chức năng excel nhưng với tính linh hoạt để thay đổi trục của nó)R thêm dữ liệu vào biểu đồ ggplot bằng cách sử dụng viewPorts: Mở rộng Grob

tôi đã có một vài đi vào nó và tiếp tục nhấn một vấn đề với mở rộng quy mô nên cố gắng 1) là

library(grid) 
library(gridExtra) 
library(ggplot2) 
xta=data.frame(f=rnorm(37,mean=400,sd=50)) 
xta$n=0 
for(i in 1:37){xta$n[i]<-paste(sample(letters,4),collapse='')} 
xta$c=0 
for(i in 1:37){xta$c[i]<-sample((1:6),1)} 
rect=data.frame(xmi=seq(0.5,36.5,1),xma=seq(1.5,37.5,1),ymi=0,yma=10) 
xta=cbind(xta,rect) 
a = ggplot(data=xta,aes(x=n,y=f,fill=c)) + geom_bar(stat='identity') 
b = ggplot(data=xta,aes(x=n,y=5,label=round(f,1))) + geom_text(size=4) + geom_rect(aes(xmin=xmi,xmax=xma,ymin=ymi,ymax=yma),alpha=0,color='black') 
z = theme(axis.text=element_blank(),panel.background=element_rect(fill='white'),axis.ticks=element_blank(),axis.title=element_blank()) 
b=b+z 
la=grid.layout(nrow=2,ncol=1,heights=c(0.15,2),default.units=c('null','null')) 
grid.show.layout(la) 
grid.newpage() 
pushViewport(viewport(layout=la)) 
print(a,vp=viewport(layout.pos.row=2,layout.pos.col=1)) 
print(b,vp=viewport(layout.pos.row=1,layout.pos.col=1)) 

mà sản xuất

2 ggplots

nỗ lực thứ hai 2) là

xta1=data.frame(t(round(xta$f,1))) 
xtb=tableGrob(xta1,show.rownames=F,show.colnames=F,show.vlines=T,gpar.corefill=gpar(fill='white',col='black'),gp=gpar(fontsize=12),vp=viewport(layout.pos.row=1,layout.pos.col=1)) 
grid.newpage() 
la=grid.layout(nrow=2,ncol=1,heights=c(0.15,2),default.units=c('null','null')) 
grid.show.layout(la) 
grid.newpage() 
pushViewport(viewport(layout=la)) 
print(a,vp=viewport(layout.pos.row=2,layout.pos.col=1)) 
grid.draw(xtb) 

mà sản xuất

using a straight table grob and grid.draw

và cuối cùng là 3) được

grid.newpage() 
print(a + annotation_custom(grob=xtb,xmin=0,xmax=37,ymin=450,ymax=460)) 

mà sản xuất

using annotate_custom

Trong số chúng, tùy chọn 2 sẽ là tốt nhất nếu tôi có thể mở rộng bảngGrob thành cùng kích thước với cốt truyện, nhưng tôi không biết cách thực hiện điều đó. Có bất kỳ gợi ý nào về cách thực hiện điều này hơn nữa không? - Cảm ơn

Trả lời

13

Bạn có thể thử phiên bản mới tableGrob; kết quả gtable chiều rộng/chiều cao có thể được thiết lập để một kích thước cụ thể (đơn vị NPC đây equi-phân phối)

library(ggplot2) 
library(gridExtra) 
library(grid) 
tg <- tableGrob(head(iris), rows=NULL) 
tg$widths <- unit(rep(1/ncol(tg),ncol(tg)),"npc") 
tg$heights <- unit(rep(1/nrow(tg),nrow(tg)),"npc") 

qplot(colnames(iris), geom="bar")+ theme_bw() + 
    scale_x_discrete(expand=c(0,0)) + 
    scale_y_continuous(lim=c(0,2), expand=c(0,0)) + 
    annotation_custom(ymin=1, ymax=2, xmin=-Inf, xmax=Inf, tg) 

enter image description here

+0

thanks @baptiste Tôi chưa có cơ hội để kiểm tra điều này. Sẽ làm như vậy vào cuối tuần nhưng điều này trông giống như câu trả lời đúng. Cảm ơn cũng cho một gói tuyệt vời –

+0

nhờ @ baptiste hoạt động như một say mê. Hoan hô! –

+0

Câu hỏi nhanh @baptiste tôi có phải tải 'source_gist' mỗi lần không? Khi bạn dự đoán tableGrob thử nghiệm sẽ nhập mã chính? –

10

Bạn có thể sử dụng ví dụ một bảng được tạo bởi ggplot và kết hợp chúng với nhau như thế này trong blog này. Tôi đã thực hiện một ví dụ đơn giản và làm việc ở đây:

Đầu tiên tạo ra âm mưu của bạn:

library(ggplot2) 
library(reshape2) 
library(grid) 

df <- structure(list(City = structure(c(2L, 
    3L, 1L), .Label = c("Minneapolis", "Phoenix", 
    "Raleigh"), class = "factor"), January = c(52.1, 
    40.5, 12.2), February = c(55.1, 42.2, 16.5), 
    March = c(59.7, 49.2, 28.3), April = c(67.7, 
     59.5, 45.1), May = c(76.3, 67.4, 57.1), 
    June = c(84.6, 74.4, 66.9), July = c(91.2, 
     77.5, 71.9), August = c(89.1, 76.5, 
     70.2), September = c(83.8, 70.6, 60), 
    October = c(72.2, 60.2, 50), November = c(59.8, 
     50, 32.4), December = c(52.5, 41.2, 
     18.6)), .Names = c("City", "January", 
    "February", "March", "April", "May", "June", 
    "July", "August", "September", "October", 
    "November", "December"), class = "data.frame", 
    row.names = c(NA, -3L)) 

dfm <- melt(df, variable = "month") 

levels(dfm$month) <- month.abb 
p <- ggplot(dfm, aes(month, value, group = City, 
    colour = City)) 
p1 <- p + geom_line(size = 1) + theme(legend.position = "top") + xlab("") 

Tiếp theo tạo bảng dữ liệu trong ggplot. Sử dụng cùng một trục x như cốt truyện:

none <- element_blank() 
data_table <- ggplot(dfm, aes(x = month, y = factor(City), 
    label = format(value, nsmall = 1), colour = City)) + 
    geom_text(size = 3.5) + 
    scale_y_discrete(labels = abbreviate)+ theme_bw() + 
    theme(panel.grid.major = none, legend.position = "none", 
     panel.border = none, axis.text.x = none, 
     axis.ticks = none) + theme(plot.margin = unit(c(-0.5, 
    1, 0, 0.5), "lines")) + xlab(NULL) + ylab(NULL) 

Kết hợp hai với khung nhìn:

Layout <- grid.layout(nrow = 2, ncol = 1, heights = unit(c(2, 
    0.25), c("null", "null"))) 
grid.show.layout(Layout) 
vplayout <- function(...) { 
    grid.newpage() 
    pushViewport(viewport(layout = Layout)) 
} 

subplot <- function(x, y) viewport(layout.pos.row = x, 
    layout.pos.col = y) 

mmplot <- function(a, b) { 
    vplayout() 
    print(a, vp = subplot(1, 1)) 
    print(b, vp = subplot(2, 1)) 
} 

mmplot(p1, data_table) 

Lưu ý rằng vẫn còn một số tinh chỉnh là cần thiết như vị trí của các huyền thoại của cốt truyện và abbrevation của tên thành phố trong bảng, nhưng kết quả có vẻ tốt đẹp: enter image description here

Áp dụng cho ví dụ của bạn:

library(grid) 
library(gridExtra) 
library(ggplot2) 
xta=data.frame(f=rnorm(37,mean=400,sd=50)) 
xta$n=0 
for(i in 1:37){xta$n[i]<-paste(sample(letters,4),collapse='')} 
xta$c=0 
for(i in 1:37){xta$c[i]<-sample((1:6),1)} 
rect=data.frame(xmi=seq(0.5,36.5,1),xma=seq(1.5,37.5,1),ymi=0,yma=10) 
xta=cbind(xta,rect) 
a = ggplot(data=xta,aes(x=n,y=f,fill=c)) + geom_bar(stat='identity')+ theme(legend.position = "top")+xlab("") 

none <- element_blank() 
z=ggplot(xta, aes(x = n, y = "fvalues", 
    label = round(f,1)))+ 
    geom_text(size = 3)+ theme_bw() + 
    theme(panel.grid.major = none, legend.position = "none", 
     panel.border = none, axis.text.x = none, 
     axis.ticks = none) + theme(plot.margin = unit(c(-0.5, 
    1, 0, 0.5), "lines")) + xlab(NULL) + ylab(NULL) 

Layout <- grid.layout(nrow = 2, ncol = 1, heights = unit(c(2, 
    0.25), c("null", "null"))) 
grid.show.layout(Layout) 
vplayout <- function(...) { 
    grid.newpage() 
    pushViewport(viewport(layout = Layout)) 
} 

subplot <- function(x, y) viewport(layout.pos.row = x, 
    layout.pos.col = y) 

mmplot <- function(a, b) { 
    vplayout() 
    print(a, vp = subplot(1, 1)) 
    print(b, vp = subplot(2, 1)) 
} 

mmplot(a, z) 

enter image description here

EDIT:

tương tự như Dennis giải pháp của mình nhưng hơn một barplot và với + coord_flip(). Bạn có thể xóa sau này nếu bạn không muốn lật nó, nhưng nó làm tăng khả năng đọc:

ggplot(xta, aes(x=n,y=f,fill=c)) + 
    geom_bar() + 
    labs(color = "c") + 
    geom_text(aes(y = max(f)+30, label = round(f, 1)), size = 3, color = "black") + coord_flip() 
+0

Cảm ơn @ JT85 này rất hữu ích và tôi đã xem blog đó. Nỗ lực đầu tiên của tôi (không sử dụng tableGrob) về cơ bản chính xác là quá trình đó nhưng với các cuộc gọi hàm được xóa và hình chữ nhật xung quanh các số. Tôi biết tôi có thể làm cho nó hoạt động nếu tôi di chuyển truyền thuyết, nhưng tôi đang cố gắng thay đổi kích thước của grob để đồ họa không thay đổi đồ họa để cho phép dữ liệu được hiển thị. Điều này là rất gần những gì tôi cần mặc dù. –

+1

Tôi đã thêm một giải pháp khác vào câu trả lời. – JT85

+0

cảm ơn @ JT85. Đây chắc chắn là một giải pháp, nhưng tôi muốn nhận được một bảng dữ liệu thực tế nếu có thể. Nếu bạn không nhớ, tôi sẽ không đánh dấu câu trả lời này là câu trả lời vì nó vẫn trông giống như một chú giải chứ không phải là một bảng riêng biệt cho các giá trị. Tôi có một cái nhìn rõ ràng và cảm giác tôi sẽ làm. –

2

IMHO đây không phải là đồ họa được thiết kế tốt. Thứ nhất, tôi không hiểu tại sao bạn cần một nguồn gốc bằng không khi các giá trị nằm trong khoảng từ 300 đến 500, đó là một cách ngụy trang nói rằng tôi không thích phép ẩn dụ biểu đồ thanh.Bạn cũng đang cố gắng sử dụng điền vào thanh để đại diện cho sự khác biệt trong các giá trị của c, trong đó chỉ có sáu. Dưới đây là những gì tôi tin là một cách tiếp cận đơn giản hơn cho vấn đề. Với dữ liệu xta của bạn,

# Convert the categories to a factor 
xta$N <- factor(xta$n, levels = xta$n) 

# Simple approach: 
ggplot(xta, aes(x = f, y = N, color = factor(c))) + 
    geom_point() + 
    labs(color = "c") + 
    geom_text(aes(x = 575, label = round(f, 1)), size = 4, color = "black") 

Đó không phải là một hình ảnh thú vị với tôi. Điều gì có thể thêm một chút thông tin chi tiết, tùy thuộc vào bối cảnh của vấn đề, sẽ được sắp xếp các phản ứng theo thứ tự tăng dần và thêm một kích thước thẩm mỹ để chấm dứt sự khác biệt giữa các cấp c. (Bạn cũng có thể sử dụng kích thước không có màu.) Cuối cùng, vì chúng tôi đặt các mức hệ số trên trục thẳng đứng sao cho nhãn của chúng hiển thị rõ ràng, chúng tôi cũng có thể chèn các giá trị f dưới dạng văn bản bằng cách mở rộng trục ngang một chút.

ggplot(xta, aes(x = f, y = reorder(N, f), color = factor(c), size = c)) + 
    geom_point() + 
    labs(color = "c") + 
    geom_text(aes(x = 575, label = round(f, 1)), size = 4, color = "black") 

Có đủ gợi ý trong mã này để bạn thực hiện theo một hướng khác. Tôi sẽ để điều đó cho bạn.

+1

cảm ơn cho đầu vào @Dennis. Dữ liệu thực tế được sắp xếp và tập dữ liệu phù hợp hơn với việc sử dụng thanh chặn. Tôi đã nghĩ về dấu chấm nhưng đối với khán giả của tôi, tôi mong đợi nó sẽ đơn giản gây nhầm lẫn các vấn đề bởi vì họ không quen thuộc với đồ họa. Tôi đánh giá cao đầu vào mặc dù. Tôi sẽ sử dụng một dấu chấm cho một trợ giúp trực quan riêng biệt trong cùng một dự án. –