ggplot:如何在geom_polygon中产生渐变填充 [英] ggplot: How to produce a gradient fill within a geom_polygon

查看:210
本文介绍了ggplot:如何在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(限制= c(1,4),low =lightgrey,high =red)

我想要的是沿着x轴的渐变,但是上面我只会看到带有渐变的图例和带有实心填充的多边形。



解决方案

当您有一个相对简单的多边形。我们不是创建多边形,而是创建大量线段并通过渐变为它们着色。结果将看起来像一个带有渐变的多边形。

 #为'n'段创建数据
n_segs< ; - 1000

#x和xend是数据中存在的'x'的整个范围的序列
newpolydata< - data.frame(xstart = seq(min(tri_fill $ x ),max(tri_fill $ x),length.out = n_segs))
newpolydata $ xend< - newpolydata $ xstart


#y's有点复杂:when x在变化点以下,y等于max(y)
#但当x高于变化点时,多边形的边界
#根据公式y =截距+ x *斜率遵循一条直线。
$ b #identify changepoint(非常数据/形状相关)
change_point < - max(tri_fill $ x [其中(tri_fill $ y == max(tri_fill $ y))]]

#calculate斜率和截距
slope < - (max(tri_fill $ y)-min(tri_fill $ y))/(change_point - max(tri_fill $ x))
截距< - 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,$ b $ 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 = c(0.75,4),low =lightgrey,high =red)
p2#注意我已经改变了渐变的下边框。



编辑:上面的解决方案如果只想要一个具有渐变的多边形,则工作正常,但是,正如在注释中指出的那样,当您计划将一个事物填充到另一个事物并将其着色时,因为每个'aes'只能使用一次。因此,我已经修改了解决方案,而不是绘制线条,而是绘制(非常薄)多边形,可以填充aes。

  #为每个多边形的'id'/多边形,四个x变量和四个y变量
#,我们从左下角开始,然后到左上角,右上角,然后再到右下角。


n_polys < - 1000
#identify变化点(非常符合数据/形状)
change_point < - max(tri_fill $ x [which(tri_fill $ y == max(tri_fill $ y))])

#calculate斜率和截距
slope < - (max(tri_fill $ y)-min(tri_fill $ y))/(change_point - max(tri_fill $ x))
截距< - max(tri_fill $ y)
#calculate边界序列:x,以及伴随的低位和高位y坐标
x_seq < - seq (x_seq <= change_point,max(tri_fill $ x),max(tri_fill $ x),max(tri_fill $ x),length.out = n_polys + 1)
y_max_seq< - ifelse change_point)* slope)
y_min_seq< - rep(min(tri_fill $ y),n_polys + 1)

#create polygons / rectangles
poly_list< - lapply(1 :n_polys,函数(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,po ly_list)

#plot,允许填充和颜色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


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.

解决方案

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. Therefore I have modified the solution to not plot lines, but to plot (very thin) polygons which can have a fill 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

这篇关于ggplot:如何在geom_polygon中产生渐变填充的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆