2012-03-03 100 views
4

我有我想繪製的以下數據框。我想知道是否可以使用不同顏色對連接我的結果變量(stackOne $ y)的部分線進行着色,具體取決於它是否小於某個值。例如,我想讓部分線條降到2.2以下,顏色變成紅色。如何根據特定值獲取geom_line的多種顏色

id<-rep(c(1,2,3),each=3) 
y<-rnorm(9,2,1) 
x<-rep(c(1,2,3),3) 
stackOne<-data.frame(cbind(id,y,x)) 
p<-ggplot(stackOne,aes(x=x,y=y)) + 
geom_point()+ 
geom_line(aes(group=id)) 
p 

謝謝!

回答

9

這裏至少有幾個選項。第一個很簡單,一般(因爲它不限於直線段)和精確的,但使用基地plot而不是ggplot。第二個使用ggplot,但稍微複雜一些,並且顏色過渡不會100%精確(但是隻要您指定了適當的分辨率......就可以了)。

基地:

如果你願意使用base繪圖函數,而不是ggplot,你可以剪輯的圖形區域爲高於閾值(2.2),然後在您的首選顏色繪製段,並隨後剪切到閾值以下的區域,並再次以紅色繪圖。雖然第一個剪輯是絕對不必要的,但它可以防止重疊繪製不同的顏色,這看起來有點不合時宜。

threshold <- 2.2 
set.seed(123) 
stackOne=data.frame(id=rep(c(1,2,3),each=3), 
       y=rnorm(9,2,1), 
       x=rep(c(1,2,3),3)) 
# create a second df to hold segment data 
d <- stackOne 
d$y2 <- c(d$y[-1], NA) 
d$x2 <- c(d$x[-1], NA) 
d <- d[-findInterval(unique(d$id), d$id), ] # remove last row for each group 

plot(stackOne[, 3:2], pch=20) 
# clip to region above the threshold 
clip(min(stackOne$x), max(stackOne$x), threshold, max(stackOne$y)) 
segments(d$x, d$y, d$x2, d$y2, lwd=2) 
# clip to region below the threshold 
clip(min(stackOne$x), max(stackOne$x), min(stackOne$y), threshold) 
segments(d$x, d$y, d$x2, d$y2, lwd=2, col='red') 
points(stackOne[, 3:2], pch=20) # plot points again so they lie over lines 

base package, changing line colours

ggplot:

如果你想要或需要使用ggplot,您可以考慮以下...

一種解決方案是使用geom_line(aes(group=id, color = y < 2.2)),然而這將根據每個片段開頭的點的y值來分配顏色。我相信你希望顏色不僅在節點上發生變化,而且在任何一條線越過給定的閾值2.2時。我並不是所有人都熟悉ggplot,但實現此目的的一種方法是通過沿連接現有點的線創建新點來創建數據的更高分辨率版本,然後使用color = y < 2.2參數來實現所需的影響。

例如:

threshold <- 2.2 # set colour-transition threshold 
yres <- 0.01 # y-resolution (accuracy of colour change location) 

d <- stackOne # for code simplification 
# new cols for point coordinates of line end 
d$y2 <- c(d$y[-1], NA) 
d$x2 <- c(d$x[-1], NA) 
d <- d[-findInterval(unique(d$id), d$id), ] # remove last row for each group 
# new high-resolution y coordinates between each pair within each group 
y.new <- apply(d, 1, function(x) { 
    seq(x['y'], x['y2'], yres*sign(x['y2'] - x['y'])) 
}) 
d$len <- sapply(y.new, length) # length of each series of points 
# new high-resolution x coordinates corresponding with new y-coords 
x.new <- apply(d, 1, function(x) { 
    seq(x['x'], x['x2'], length.out=x['len']) 
}) 
id <- rep(seq_along(y.new), d$len) # new group id vector 
y.new <- unlist(y.new) 
x.new <- unlist(x.new) 
d.new <- data.frame(id=id, x=x.new, y=y.new) 

p <- ggplot(d.new, aes(x=x,y=y)) + 
    geom_line(aes(group=d.new$id, color=d.new$y < threshold))+ 
    geom_point(data=stackOne)+ 
    scale_color_discrete(sprintf('Below %s', threshold)) 
p 

conditional line colour - ggplot

有可能是一種方法,通過ggplot功能,要做到這一點,但在此期間,我希望這會有所幫助。我無法弄清楚如何將ggplotGrob繪製成修剪後的viewport(而似乎只是縮放繪圖)。如果你想要顏色取決於某個x值閾值,這顯然需要一些調整。

+0

謝謝。我聽說融化函數也可能對這些問題有用,但這聽起來像是一個很好的解決方案。 – user1106711 2012-03-03 18:25:45

+0

我已經編輯瞭解決方案,包括一個使用基本圖和'clip'的方法。 – jbaums 2012-03-04 05:22:22

+0

'ggplotGrob'使用內部視口本身,這就是裁剪不起作用的原因。 – baptiste 2012-03-04 07:41:33