這裏建立在@ Andrie的回答是處理上面或在多數情況下給定線下方陰影更(但不完全)通用的解決方案。
當您添加邊緣附近點我沒有使用@Andrie引用here,因爲我遇到了與ggplot
的傾向自動延長情節程度問題的方法。相反,這種構建多邊形點使用Inf
和-Inf
根據需要手動。有幾個注意事項:
的點必須在數據幀中的「正確」的順序,因爲ggplot
地塊,該點出現的順序多邊形。所以獲得多邊形的頂點是不夠的,它們必須被順序排列(順時針或逆時針)。
此解決方案假定您正在繪製行本身並不引起ggplot
延伸繪圖範圍。在我的示例中,您會看到我通過在數據中隨機選擇兩個點並通過它們繪製線來選取一條線進行繪製。如果您嘗試畫一條線過於遠離你點的休息,ggplot
會自動改變劇情的範圍,並且變得很難預測他們會是什麼。
首先,這裏是建立多邊數據幀的功能:
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)
}
它預計數據的X和Y範圍(如range()
),斜率和截距行的你將要繪製,並且您是否想要遮蔽線條的上方或下方。以下是我用於生成以下四個示例的代碼:
#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)
下面是一些結果示例。如果您發現任何錯誤,當然,讓我知道,這樣我可以更新這個答案...
編輯
已更新使用OP的示例性數據說明的解決方案:
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)
並且這產生以下輸出:
着色點和填充多邊形是由兩個不同的美學處理(顏色和填充)和不應該發生衝突,所以我懷疑你可能在那裏做錯了什麼。我很樂意提供更多的幫助,但是如果沒有您想要繪製的數據的特定重現示例,我不能這麼做...... – joran
完成。我懷疑這起源於我對ggplot2如何處理這些事情的陌生性。再次感謝您的幫助,我非常感謝。 – jslefche
將'color = var1'移動到'geom_point':'geom_point(aes(color = var1),...)'。另外,如果你想在每個方面填充不同的多邊形,你應該知道你必須爲每個方面創建一個單獨的數據框,並將它們組合成一個包含'var2'因子的數據框,所以'ggplot'知道哪一個適用於每個方面。 – joran