2015-11-27 14 views
5

Questo dovrebbe essere abbastanza facile, ma non riesco a trovare la mia strada attraverso.ggplot: come produrre un riempimento sfumato all'interno di un geom_polygon

tri_fill <- structure(
    list(x= c(0.75, 0.75, 2.25, 3.25), 
     y = c(40, 43, 43, 40)), 
    .Names = c("x", "y"), 
    row.names = c(NA, -4L), class = "data.frame",Integrated=NA, Related=NA) 

# install.packages("ggplot2", dependencies = TRUE) 
require(ggplot2) 


    ggplot(data=tri_fill,aes(x=x, y=y))+ 
     geom_polygon() + 
     scale_fill_gradient(limits=c(1, 4), low = "lightgrey", high = "red") 

Quello che voglio è un gradiente lungo l'asse x, ma con quanto sopra ho solo una leggenda con un gradiente e il poligono con riempimento solido.

plot

+0

Questo non è banale, come poligoni hanno un solo colore di riempimento. Alla fine il tuo poligono desiderato è "semplice" o più complicato? – Heroka

risposta

5

Ecco una possibile soluzione per quando si ha una relativamente semplice poligono. Invece di un poligono, creiamo molti segmenti di linea e li coloriamo di un gradiente. Il risultato sarà quindi un poligono con un gradiente.

#create data for 'n'segments 
n_segs <- 1000 

#x and xend are sequences spanning the entire range of 'x' present in the data 
newpolydata <- data.frame(xstart=seq(min(tri_fill$x),max(tri_fill$x),length.out=n_segs)) 
newpolydata$xend <- newpolydata$xstart 


#y's are a little more complicated: when x is below changepoint, y equals max(y) 
#but when x is above the changepoint, the border of the polygon 
#follow a line according to the formula y= intercept + x*slope. 

#identify changepoint (very data/shape dependent) 
change_point <- max(tri_fill$x[which(tri_fill$y==max(tri_fill$y))]) 

#calculate slope and intercept 
slope <- (max(tri_fill$y)-min(tri_fill$y))/ (change_point - max(tri_fill$x)) 
intercept <- max(tri_fill$y) 

#all lines start at same y 
newpolydata$ystart <- min(tri_fill$y) 

#calculate y-end 
newpolydata$yend <- with(newpolydata, ifelse (xstart <= change_point, 
         max(tri_fill$y),intercept+ (xstart-change_point)*slope)) 

p2 <- ggplot(newpolydata) + 
    geom_segment(aes(x=xstart,xend=xend,y=ystart,yend=yend,color=xstart)) + 
    scale_color_gradient(limits=c(0.75, 4), low = "lightgrey", high = "red") 
p2 #note that I've changed the lower border of the gradient. 

enter image description here

EDIT: sopra soluzione funziona se si desidera solo un poligono con un gradiente, però, come è stato sottolineato nei commenti questo può dare problemi quando si stavano progettando di mappare una cosa da riempire e un'altra cosa da colorare, dato che ogni 'aes' può essere usata solo una volta. Quindi ho modificato la soluzione per non tracciare linee, ma per tracciare poligoni (molto sottili) che possono avere un riempimento aes.

#for each 'id'/polygon, four x-variables and four y-variable 
#for each polygon, we start at lower left corner, and go to upper left, upper right and then to lower right. 


n_polys <- 1000 
#identify changepoint (very data/shape dependent) 
change_point <- max(tri_fill$x[which(tri_fill$y==max(tri_fill$y))]) 

#calculate slope and intercept 
slope <- (max(tri_fill$y)-min(tri_fill$y))/ (change_point - max(tri_fill$x)) 
intercept <- max(tri_fill$y) 
#calculate sequence of borders: x, and accompanying lower and upper y coordinates 
x_seq <- seq(min(tri_fill$x),max(tri_fill$x),length.out=n_polys+1) 
y_max_seq <- ifelse(x_seq<=change_point, max(tri_fill$y), intercept + (x_seq - change_point)*slope) 
y_min_seq <- rep(min(tri_fill$y), n_polys+1) 

#create polygons/rectangles 
poly_list <- lapply(1:n_polys, function(p){ 
    res <- data.frame(x=rep(c(x_seq[p],x_seq[p+1]),each=2), 
        y = c(y_min_seq[p], y_max_seq[p:(p+1)], y_min_seq[p+1])) 
    res$fill_id <- x_seq[p] 
    res 
} 
) 

poly_data <- do.call(rbind, poly_list) 

#plot, allowing for both fill and color-aes 
p3 <- ggplot(tri_fill, aes(x=x,y=y))+ 
    geom_polygon(data=poly_data, aes(x=x,y=y, group=fill_id,fill=fill_id)) + 
    scale_fill_gradient(limits=c(0.75, 4), low = "lightgrey", high = "red") + 
    geom_point(aes(color=factor(y)),size=5) 
p3 

enter image description here

+0

Grazie, Heroka. Posso riprodurre il tuo gradiente. Tuttavia, questo dovrebbe andare su un'altra trama (con molte più geom e scale) che lo rende un po 'complicato .... – Almstrup

+0

Puoi aggiornare il tuo esempio? Perché non può andare oltre qualcos'altro? – Heroka

+0

Tracciandolo sotto qualcos'altro potrebbe essere meglio, vieni a pensarci. – Heroka

Problemi correlati