2011-07-23 25 views
6

Tôi có một số dữ liệu bị hạn chế bên dưới dòng 1: 1. Tôi sẽ chứng minh điều này trên một âm mưu bằng cách che khuất nhẹ khu vực TRÊN đường kẻ, để thu hút sự chú ý của người xem đến khu vực bên dưới dòng.ggplot2 - Vùng bóng râm phía trên dòng

Tôi đang sử dụng qplot để tạo biểu đồ. Nhanh chóng, tôi có;

qplot(x,y)+geom_abline(slope=1)

nhưng đối với cuộc sống của tôi, không thể tìm ra cách để dễ dàng che khu vực trên mà không âm mưu một đối tượng riêng biệt. Có một sửa chữa dễ dàng cho điều này?


EDIT

Ok, Joran, đây là một bộ dữ liệu ví dụ:

df=data.frame(x=runif(6,-2,2),y=runif(6,-2,2), 
    var1=rep(c("A","B"),3),var2=rep(c("C","D"),3)) 
df_poly=data.frame(x=c(-Inf, Inf, -Inf),y=c(-Inf, Inf, Inf)) 

và đây là mã mà tôi đang sử dụng để vẽ nó (tôi lấy lời khuyên của bạn và đã được tìm kiếm ggplot()):

ggplot(df,aes(x,y,color=var1))+ 
facet_wrap(~var2)+ 
geom_abline(slope=1,intercept=0,lwd=0.5)+ 
geom_point(size=3)+ 
scale_color_manual(values=c("red","blue"))+ 
geom_polygon(data=df_poly,aes(x,y),fill="blue",alpha=0.2) 

Erro r kicked trở lại là: "đối tượng 'var1' không tìm thấy" Một cái gì đó nói với tôi rằng tôi đang thực hiện các đối số không chính xác ...

+0

điểm màu và đa giác điền được xử lý bởi hai thẩm mỹ khác nhau (màu sắc và điền vào) và không nên xung đột, vì vậy tôi nghi ngờ bạn có thể làm điều gì đó sai trái ở đó. Tôi rất sẵn lòng trợ giúp thêm một số nhưng tôi không thể không có một ví dụ tái tạo cụ thể về dữ liệu bạn đang cố gắng vẽ ... – joran

+0

Xong. Tôi nghi ngờ điều này xuất phát từ sự không quen thuộc của tôi với cách ggplot2 xử lý những thứ như vậy. Cảm ơn một lần nữa vì sự giúp đỡ của bạn, tôi đánh giá cao nó rất nhiều. – jslefche

+0

Di chuyển 'color = var1' thành' geom_point': 'geom_point (aes (color = var1), ...)'. Ngoài ra, nếu bạn muốn các đa giác khác nhau trong mỗi khía cạnh nhận thức được rằng bạn sẽ phải tạo một khung dữ liệu riêng biệt cho từng khía cạnh và kết hợp chúng thành một khung dữ liệu đơn bao gồm yếu tố 'var2', vì vậy' ggplot' biết cái nào áp dụng cho từng khía cạnh. – joran

Trả lời

11

Dựa trên câu trả lời @ Andrie ở đây là một nhiều hơn (nhưng không hoàn toàn) giải pháp chung để xử lý bóng trên hoặc dưới một đường thẳng cho trước trong hầu hết các trường hợp.

Tôi không sử dụng phương thức @Andrie đã tham chiếu here vì tôi gặp sự cố với xu hướng tự động mở rộng cốt truyện của ggplot khi bạn thêm điểm gần các cạnh. Thay vào đó, việc này sẽ tạo các điểm đa giác theo cách thủ công bằng cách sử dụng Inf-Inf khi cần. Một vài lưu ý:

  • Những điểm cần phải theo thứ tự chính xác 'trong khung dữ liệu, vì ggplot lô đa giác theo thứ tự mà các điểm xuất hiện. Vì vậy, nó không đủ để có được các đỉnh của đa giác, họ phải được đặt hàng (hoặc là chiều kim đồng hồ hoặc ngược chiều kim đồng hồ) là tốt.

  • Giải pháp này giả định rằng dòng bạn đang vẽ không tự gây ra ggplot để mở rộng phạm vi ô. Bạn sẽ thấy trong ví dụ của tôi rằng tôi chọn một dòng để vẽ bằng cách chọn ngẫu nhiên hai điểm trong dữ liệu và vẽ đường thẳng qua chúng. Nếu bạn cố gắng vẽ một đường quá xa các điểm còn lại của bạn, ggplot sẽ tự động thay đổi phạm vi ô và sẽ khó đoán được chúng sẽ là gì.

Thứ nhất, đây là chức năng mà xây dựng các khung dữ liệu đa giác:

buildPoly <- function(xr, yr, slope = 1, intercept = 0, above = TRUE){ 
    #Assumes ggplot default of expand = c(0.05,0) 
    xrTru <- xr + 0.05*diff(xr)*c(-1,1) 
    yrTru <- yr + 0.05*diff(yr)*c(-1,1) 

    #Find where the line crosses the plot edges 
    yCross <- (yrTru - intercept)/slope 
    xCross <- (slope * xrTru) + intercept 

    #Build polygon by cases 
    if (above & (slope >= 0)){ 
     rs <- data.frame(x=-Inf,y=Inf) 
     if (xCross[1] < yrTru[1]){ 
      rs <- rbind(rs,c(-Inf,-Inf),c(yCross[1],-Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(-Inf,xCross[1])) 
     } 
     if (xCross[2] < yrTru[2]){ 
      rs <- rbind(rs,c(Inf,xCross[2]),c(Inf,Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[2],Inf)) 
     } 
    } 
    if (!above & (slope >= 0)){ 
     rs <- data.frame(x= Inf,y= -Inf) 
     if (xCross[1] > yrTru[1]){ 
      rs <- rbind(rs,c(-Inf,-Inf),c(-Inf,xCross[1])) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[1],-Inf)) 
     } 
     if (xCross[2] > yrTru[2]){ 
      rs <- rbind(rs,c(yCross[2],Inf),c(Inf,Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(Inf,xCross[2])) 
     } 
    } 
    if (above & (slope < 0)){ 
     rs <- data.frame(x=Inf,y=Inf) 
     if (xCross[1] < yrTru[2]){ 
      rs <- rbind(rs,c(-Inf,Inf),c(-Inf,xCross[1])) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[2],Inf)) 
     } 
     if (xCross[2] < yrTru[1]){ 
      rs <- rbind(rs,c(yCross[1],-Inf),c(Inf,-Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(Inf,xCross[2])) 
     } 
    } 
    if (!above & (slope < 0)){ 
     rs <- data.frame(x= -Inf,y= -Inf) 
     if (xCross[1] > yrTru[2]){ 
      rs <- rbind(rs,c(-Inf,Inf),c(yCross[2],Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(-Inf,xCross[1])) 
     } 
     if (xCross[2] > yrTru[1]){ 
      rs <- rbind(rs,c(Inf,xCross[2]),c(Inf,-Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[1],-Inf)) 
     } 
    } 

    return(rs) 
} 

Nó hy vọng x và y dãy dữ liệu của bạn (như trong range()), độ dốc và đánh chặn của dòng bạn sẽ âm mưu, và liệu bạn có muốn che bóng ở trên hay dưới dòng. Đây là mã tôi đã sử dụng để tạo bốn ví dụ sau:

#Generate some data 
dat <- data.frame(x=runif(10),y=runif(10)) 

#Select two of the points to define the line 
pts <- dat[sample(1:nrow(dat),size=2,replace=FALSE),] 

#Slope and intercept of line through those points 
sl <- diff(pts$y)/diff(pts$x) 
int <- pts$y[1] - (sl*pts$x[1]) 

#Build the polygon 
datPoly <- buildPoly(range(dat$x),range(dat$y), 
      slope=sl,intercept=int,above=FALSE) 

#Make the plot 
p <- ggplot(dat,aes(x=x,y=y)) + 
     geom_point() + 
     geom_abline(slope=sl,intercept = int) + 
     geom_polygon(data=datPoly,aes(x=x,y=y),alpha=0.2,fill="blue") 
print(p)  

Và đây là một số ví dụ về kết quả. Nếu bạn tìm thấy bất kỳ lỗi, tất nhiên, cho tôi biết để tôi có thể cập nhật câu trả lời này ...

shade_above1

shade_above2

shade_below1

shade_below2

EDIT

Đã cập nhật lên minh họa giải pháp sử dụng dữ liệu ví dụ OP của:

set.seed(1) 
dat <- data.frame(x=runif(6,-2,2),y=runif(6,-2,2), 
     var1=rep(c("A","B"),3),var2=rep(c("C","D"),3)) 
#Create polygon data frame 
df_poly <- buildPoly(range(dat$x),range(dat$y)) 

ggplot(data=dat,aes(x,y)) + 
    facet_wrap(~var2) + 
    geom_abline(slope=1,intercept=0,lwd=0.5)+ 
    geom_point(aes(colour=var1),size=3) + 
    scale_color_manual(values=c("red","blue"))+ 
    geom_polygon(data=df_poly,aes(x,y),fill="blue",alpha=0.2) 

và điều này sẽ cho kết quả như sau:

enter image description here

+0

+1 Đẹp một .... – Andrie

+0

Xem ở trên để nhận xét của tôi! – jslefche

5

Theo tôi biết không có cách nào khác ngoài việc tạo ra một đa giác với alpha pha trộn lấp đầy. Ví dụ:

df <- data.frame(x=1, y=1) 
df_poly <- data.frame(
    x=c(-Inf, Inf, -Inf), 
    y=c(-Inf, Inf, Inf) 
) 

ggplot(df, aes(x, y)) + 
    geom_blank() + 
    geom_abline(slope=1, intercept=0) + 
    geom_polygon(data=df_poly, aes(x, y), fill="blue", alpha=0.2) + 

enter image description here

+0

Mọi thứ trở nên phức tạp hơn nhiều nếu dòng không chạy từ góc này sang góc khác, điều này có khả năng xảy ra nếu dòng được vẽ trên đầu trang của một tập hợp dữ liệu khác. Tôi leng keng một chút nhưng không thể nghĩ ra một giải pháp chung. – joran

+0

Giải pháp chung phải nằm dọc theo các dòng như được mô tả trong http://stackoverflow.com/questions/6786982/shaded-area-under-two-curves-using-r/6787479#6787479 – Andrie

+0

Cảm ơn các giải pháp của bạn! Tôi đã thử Andrie's, nhưng tôi đã xác định rằng các điểm được tô màu bởi một biến thứ ba 'qplot (x, y, color = z)', mà không chơi tốt với câu lệnh 'geom_polygon()'. Dòng này cũng bị lệch thấp hơn nguồn gốc, mà tôi không thể hiểu được. Bất kỳ ý tưởng? – jslefche

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