简体   繁体   English

ggplot:如何在 geom_polygon 中生成渐变填充

[英]ggplot: How to produce a gradient fill within a geom_polygon

This should be fairly easy but I can't find my way thru.这应该相当容易,但我找不到路。

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")

What I want is a gradient along the x-axis, but with the above I only get a legend with a gradient and the polygon with solid fill.我想要的是沿 x 轴的渐变,但在上面我只得到一个带有渐变的图例和带有实心填充的多边形。

阴谋

Here is a possible solution for when you have a relatively simple polygon.当您有一个相对简单的多边形时,这是一个可能的解决方案。 Instead of a polygon, we create lots of line-segments and color them by a gradient.我们创建了许多线段并通过渐变为它们着色,而不是多边形。 The result will thus look like a polygon with a gradient.因此,结果看起来像一个带有渐变的多边形。

#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.

在此处输入图片说明

EDIT: above solution works if one only desires a polygon with a gradient, however, as was pointed out in the comments this can give problems when you were planning to map one thing to fill and another thing to color, as each 'aes' can only be used once.编辑:如果您只需要一个带有渐变的多边形,则上述解决方案有效,但是,正如评论中指出的那样,当您计划将一个东西映射到填充并将另一个东西映射到颜色时,这可能会产生问题,因为每个“aes”都可以只能使用一次。 Therefore I have modified the solution to not plot lines, but to plot (very thin) polygons which can have a fill aes.因此,我修改了解决方案,不绘制线条,而是绘制可以具有填充 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

在此处输入图片说明

在这个关于热映射三角形的问题中找到的答案实现了相同的效果,可用于任何复杂的多边形形状。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM