2014-12-02 73 views
6

如何填充區域以下(sp)行漸變色如何使漸變色填充時間序列圖R

此示例已繪製在Inkscape中 - 但我需要垂直梯度 - 非水平。

間隔由白色紅色積極 ==。

區間從零白色紅色 ==

enter image description here

是否有任何可能做到這一點?

我製造了一些源數據....

set.seed(1) 
x<-seq(from = -10, to = 10, by = 0.25) 
data <- data.frame(value = sample(x, 25, replace = TRUE), time = 1:25) 
plot(data$time, data$value, type = "n") 
my.spline <- smooth.spline(data$time, data$value, df = 15) 
lines(my.spline$x, my.spline$y, lwd = 2.5, col = "blue") 
abline(h = 0) 

回答

6

下面是在base R,我們填充漸變色的矩形整個小區面積的方法,並隨後填寫的白色感興趣的區域的倒數。

shade <- function(x, y, col, n=500, xlab='x', ylab='y', ...) { 
    # x, y: the x and y coordinates 
    # col: a vector of colours (hex, numeric, character), or a colorRampPalette 
    # n: the vertical resolution of the gradient 
    # ...: further args to plot() 
    plot(x, y, type='n', las=1, xlab=xlab, ylab=ylab, ...) 
    e <- par('usr') 
    height <- diff(e[3:4])/(n-1) 
    y_up <- seq(0, e[4], height) 
    y_down <- seq(0, e[3], -height) 
    ncolor <- max(length(y_up), length(y_down)) 
    pal <- if(!is.function(col)) colorRampPalette(col)(ncolor) else col(ncolor) 
    # plot rectangles to simulate colour gradient 
    sapply(seq_len(n), 
     function(i) { 
      rect(min(x), y_up[i], max(x), y_up[i] + height, col=pal[i], border=NA) 
      rect(min(x), y_down[i], max(x), y_down[i] - height, col=pal[i], border=NA) 
     }) 
    # plot white polygons representing the inverse of the area of interest 
    polygon(c(min(x), x, max(x), rev(x)), 
      c(e[4], ifelse(y > 0, y, 0), 
      rep(e[4], length(y) + 1)), col='white', border=NA)  
    polygon(c(min(x), x, max(x), rev(x)), 
      c(e[3], ifelse(y < 0, y, 0), 
      rep(e[3], length(y) + 1)), col='white', border=NA)  
    lines(x, y) 
    abline(h=0) 
    box() 
} 

下面是一些例子:

xy <- curve(sin, -10, 10, n = 1000) 
shade(xy$x, xy$y, c('white', 'blue'), 1000) 

pic1

或用顏色由彩色調色板斜坡指定:

shade(xy$x, xy$y, heat.colors, 1000) 

pic2

適用於您的數據,儘管我們首先將點插值到更精細的分辨率(如果我們不這樣做,漸變不會緊隨其過零的線)。

xy <- approx(my.spline$x, my.spline$y, n=1000) 
shade(xy$x, xy$y, c('white', 'red'), 1000) 

pic3

10

這裏有一個方法,這在很大程度上依賴於幾個R個空間包。

的基本思想是:

  • 劇情空積,在其上後續的元件將被規定的畫布。 (這樣做首先還可以檢索劇情的用戶座標,在後續步驟中需要。)

  • 使用向量化調用rect()來放置背景色。獲取顏色漸變的細節是實際操作中最棘手的部分。

  • 使用拓撲函數rgeos先找到圖中的閉合矩形,然後再補充它們。使用白色填充在背景清洗上繪製補色可以覆蓋各處的顏色,但多邊形內的除外,正是您想要的。

  • 最後,使用plot(..., add=TRUE),lines(), abline()等來確定您希望繪圖顯示的任何其他細節。


library(sp) 
library(rgeos) 
library(raster) 
library(grid) 

## Extract some coordinates 
x <- my.spline$x 
y <- my.spline$y 
hh <- 0 
xy <- cbind(x,y) 

## Plot an empty plot to make its coordinates available 
## for next two sections 
plot(data$time, data$value, type = "n", axes=FALSE, xlab="", ylab="") 

## Prepare data to be used later by rect to draw the colored background 
COL <- colorRampPalette(c("red", "white", "red"))(200) 
xx <- par("usr")[1:2] 
yy <- c(seq(min(y), hh, length.out=100), seq(hh, max(y), length.out=101)) 

## Prepare a mask to cover colored background (except within polygons) 
## (a) Make SpatialPolygons object from plot's boundaries 
EE <- as(extent(par("usr")), "SpatialPolygons") 
## (b) Make SpatialPolygons object containing all closed polygons 
SL1 <- SpatialLines(list(Lines(Line(xy), "A"))) 
SL2 <- SpatialLines(list(Lines(Line(cbind(c(0,25),c(0,0))), "B"))) 
polys <- gPolygonize(gNode(rbind(SL1,SL2))) 
## (c) Find their difference 
mask <- EE - polys 

## Put everything together in a plot 
plot(data$time, data$value, type = "n") 
rect(xx[1], yy[-201], xx[2], yy[-1], col=COL, border=NA) 
plot(mask, col="white", add=TRUE) 
abline(h = hh) 
plot(polys, border="red", lwd=1.5, add=TRUE) 
lines(my.spline$x, my.spline$y, col = "red", lwd = 1.5) 

enter image description here

7

這是欺騙ggplot去做你想要什麼可怕的方式。本質上,我製作了一個巨大的曲線下點的網格。由於無法在單個多邊形內設置漸變,因此必須製作單獨的多邊形,因此需要製作網格。如果將像素設置得太低,它會很慢。

gen.bar <- function(x, ymax, ypixel) { 
    if (ymax < 0) ypixel <- -abs(ypixel) 
    else ypixel <- abs(ypixel) 
    expand.grid(x=x, y=seq(0,ymax, by = ypixel)) 
} 

# data must be in x order. 
find.height <- function (x, data.x, data.y) { 
    base <- findInterval(x, data.x) 
    run <- data.x[base+1] - data.x[base] 
    rise <- data.y[base+1] - data.y[base] 
    data.y[base] + ((rise/run) * (x - data.x[base])) 
} 

make.grid.under.curve <- function(data.x, data.y, xpixel, ypixel) { 
    desired.points <- sort(unique(c(seq(min(data.x), max(data.x), xpixel), data.x))) 
    desired.points <- desired.points[-length(desired.points)] 

    heights <- find.height(desired.points, data.x, data.y) 
    do.call(rbind, 
      mapply(gen.bar, desired.points, heights, 
       MoreArgs = list(ypixel), SIMPLIFY=FALSE)) 
} 

xpixel = 0.01 
ypixel = 0.01 
library(scales) 
grid <- make.grid.under.curve(data$time, data$value, xpixel, ypixel) 
ggplot(grid, aes(xmin = x, ymin = y, xmax = x+xpixel, ymax = y+ypixel, 
       fill=abs(y))) + geom_rect() 

的顏色是不是你想要的,但它可能是嚴重的使用太慢反正。

enter image description here

5

其使用功能從gridgridSVG包的另一種可能性。

我們首先根據@kohskehere描述的方法通過線性插值生成附加數據點。基本圖則由兩個獨立的多邊形組成,一個用於負值,另一個用於正值。

繪製完成後,grid.ls用於顯示grob的列表,即繪圖的所有構建塊。在列表中,我們將(除其他之外)找到兩個geom_area.polygon s;一個代表值爲<= 0的多邊形,另一個代表值爲>= 0

多邊形grobs然後使用gridSVG功能操縱的填充:自定義顏色梯度與linearGradient創建,並且grobs的填充是使用grid.gradientFill替換。

grob漸變的操縱在第11章中的第7章中很好地描述了gridSVG包的作者之一Simon Potter的MSc thesis

library(grid) 
library(gridSVG) 
library(ggplot2) 

# create a data frame of spline values 
d <- data.frame(x = my.spline$x, y = my.spline$y) 

# create interpolated points 
d <- d[order(d$x),] 
new_d <- do.call("rbind", 
       sapply(1:(nrow(d) -1), function(i){ 
        f <- lm(x ~ y, d[i:(i+1), ]) 
        if (f$qr$rank < 2) return(NULL) 
        r <- predict(f, newdata = data.frame(y = 0)) 
        if(d[i, ]$x < r & r < d[i+1, ]$x) 
        return(data.frame(x = r, y = 0)) 
        else return(NULL) 
       }) 
) 

# combine original and interpolated data 
d2 <- rbind(d, new_d) 
d2 

# set up basic plot 
ggplot(data = d2, aes(x = x, y = y)) + 
    geom_area(data = subset(d2, y <= 0)) + 
    geom_area(data = subset(d2, y >= 0)) + 
    geom_line() + 
    geom_abline(intercept = 0, slope = 0) + 
    theme_bw() 

# list the name of grobs and look for relevant polygons 
# note that the exact numbers of the grobs may differ 
grid.ls() 
# GRID.gTableParent.878 
# ... 
# panel.3-4-3-4 
# ... 
#  areas.gTree.834 
#  geom_area.polygon.832 <~~ polygon for negative values 
#  areas.gTree.838 
#  geom_area.polygon.836 <~~ polygon for positive values 

# create a linear gradient for negative values, from white to red 
col_neg <- linearGradient(col = c("white", "red"), 
          x0 = unit(1, "npc"), x1 = unit(1, "npc"), 
          y0 = unit(1, "npc"), y1 = unit(0, "npc")) 

# replace fill of 'negative grob' with a gradient fill 
grid.gradientFill("geom_area.polygon.832", col_neg, group = FALSE) 

# create a linear gradient for positive values, from white to red 
col_pos <- linearGradient(col = c("white", "red"), 
          x0 = unit(1, "npc"), x1 = unit(1, "npc"), 
          y0 = unit(0, "npc"), y1 = unit(1, "npc")) 

# replace fill of 'positive grob' with a gradient fill 
grid.gradientFill("geom_area.polygon.836", col_pos, group = FALSE) 


# generate SVG output 
grid.export("myplot.svg") 

enter image description here

你可以輕鬆地創建正面和負面的多邊形不同的顏色漸變。例如。如果你想負值從白色變成藍色,而不是跑,上面替換col_pos

col_pos <- linearGradient(col = c("white", "blue"), 
          x0 = unit(1, "npc"), x1 = unit(1, "npc"), 
          y0 = unit(0, "npc"), y1 = unit(1, "npc")) 

enter image description here