在格子图中添加/代替背景颜色使用图案

发布于 2025-01-08 16:22:33 字数 201 浏览 2 评论 0原文

我正在使用 R 格子包中的水平图。我得到的图如下所示。

我现在的问题是我需要生成黑白版本进行打印。

有没有办法将颜色更改为灰度并为矩形提供背景图案,以便可以将红色与蓝色区分开来?例如,我会想到点或对角线。

谢谢!

示例图片

I am using level plots from the R lattice package. My resulting plots look like the one shown below.

My problem now is that I need to generate a black and white version for printing.

Is there a way to change the colors to grayscale and give the rectangles a background pattern so the the red once are distinguishable from the blue ones? For example, dots or diagonal dashes come to mind.

Thanks!

Example image

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橘味果▽酱 2025-01-15 16:22:33

添加点会更容易,只需在顶部添加 panel.points 即可。向图例添加点可能会有点困难。以下函数在网格图形中执行此操作。

grid.colorbar(runif(10, -2, 5))

pointsGrob
pattern

require(RColorBrewer)
require(scales)

diverging_palette <- function(d = NULL, centered = FALSE, midpoint = 0,
                              colors = RColorBrewer::brewer.pal(7,"PRGn")){

  half <- length(colors)/2

  if(!length(colors)%%2)
    stop("requires odd number of colors")
  if( !centered && !(midpoint <=  max(d) && midpoint >= min(d)))
    warning("Midpoint is outside the data range!")

  values <-  if(!centered) {
    low <- seq(min(d), midpoint, length=half)
    high <- seq(midpoint, max(d), length=half)
    c(low[-length(low)], midpoint, high[-1])
  } else {
    mabs <- max(abs(d - midpoint))
    seq(midpoint-mabs, midpoint + mabs, length=length(colors))
  }

  scales::gradient_n_pal(colors, values = values)

}

colorbarGrob <- function(d, x = unit(0.5, "npc"), 
                         y = unit(0.1,"npc"),
                         height=unit(0.8,"npc"),
                         width=unit(0.5, "cm"), size=0.7,
                         margin=unit(1,"mm"), tick.length=0.2*width,
                         pretty.breaks = grid.pretty(range(d)),
                         digits = 2, show.extrema=TRUE,
                         palette = diverging_palette(d), n = 1e2,
                         point.negative=TRUE,   gap =5,
                         interpolate=TRUE,
                         ...){

  ## includes extreme limits of the data
  legend.vals <- unique(round(sort(c(pretty.breaks, min(d), max(d))), digits)) 

  legend.labs <- if(show.extrema)
    legend.vals else unique(round(sort(pretty.breaks), digits)) 

  ## interpolate the colors
  colors <- palette(seq(min(d), max(d), length=n))
  ## 1D strip of colors, from bottom <-> min(d) to top <-> max(d)
  lg <- rasterGrob(rev(colors), # rasterGrob draws from top to bottom
                   y=y, interpolate=interpolate,
                   x=x, just=c("left", "bottom"),
                   width=width, height=height)


  ## box around color strip
  bg <- rectGrob(x=x, y=y, just=c("left", "bottom"),
                 width=width, height=height, gp=gpar(fill="transparent"))

  ## positions of the tick marks
  pos.y <- y + height * rescale(legend.vals)
  if(!show.extrema) pos.y <-  pos.y[-c(1, length(pos.y))]

  ## tick labels
  ltg <- textGrob(legend.labs, x = x + width + margin, y=pos.y,
                          just=c("left", "center"))
  ## right tick marks
  rticks <- segmentsGrob(y0=pos.y, y1=pos.y,
                         x0 = x + width,
                         x1 = x + width - tick.length,
                         gp=gpar())
  ## left tick marks
 lticks <- segmentsGrob(y0=pos.y, y1=pos.y,
                        x0 = x ,
                        x1 = x + tick.length,
                        gp=gpar())

  ## position of the dots
  if(any( d < 0 )){
  yneg <- diff(range(c(0, d[d<0])))/diff(range(d))  * height
  clipvp <- viewport(clip=TRUE, x=x, y=y, width=width, height=yneg,
                     just=c("left", "bottom"))
  h <- convertUnit(yneg, "mm", "y", valueOnly=TRUE)

  pos <- seq(0, to=h, by=gap)
  }
  ## coloured dots
  cg <- if(!point.negative || !any( d < 0 )) nullGrob() else
  pointsGrob(x=unit(rep(0.5, length(pos)), "npc"), y = y + unit(pos, "mm") ,
          pch=21, gp=gpar(col="white", fill="black"),size=unit(size*gap, "mm"), vp=clipvp)
  ## for more general pattern use the following
  ## gridExtra::patternGrob(x=unit(0.5, "npc"), y = unit(0.5, "npc") , height=unit(h,"mm"), 
  ##   pattern=1,granularity=unit(2,"mm"), gp=gpar(col="black"), vp=clipvp)

  gTree(children=gList(lg,  lticks, rticks, ltg, bg, cg),
        width = width + margin + max(stringWidth(legend.vals)), ... , cl="colorbar")
}

grid.colorbar <- function(...){
  g <- colorbarGrob(...)
  grid.draw(g)
  invisible(g)
}

widthDetails.colorbar <- function(x){
 x$width 
}

编辑:对于图案填充,您可以将 pointsGrob 替换为 gridExtra:: patternGrob (您也可以对矩阵的图块执行此操作)。

dots would be easier to add, simply adding panel.points on top. Adding points to the legend could be a bit harder. The following function does it in grid graphics.

grid.colorbar(runif(10, -2, 5))

pointsGrob
pattern

require(RColorBrewer)
require(scales)

diverging_palette <- function(d = NULL, centered = FALSE, midpoint = 0,
                              colors = RColorBrewer::brewer.pal(7,"PRGn")){

  half <- length(colors)/2

  if(!length(colors)%%2)
    stop("requires odd number of colors")
  if( !centered && !(midpoint <=  max(d) && midpoint >= min(d)))
    warning("Midpoint is outside the data range!")

  values <-  if(!centered) {
    low <- seq(min(d), midpoint, length=half)
    high <- seq(midpoint, max(d), length=half)
    c(low[-length(low)], midpoint, high[-1])
  } else {
    mabs <- max(abs(d - midpoint))
    seq(midpoint-mabs, midpoint + mabs, length=length(colors))
  }

  scales::gradient_n_pal(colors, values = values)

}

colorbarGrob <- function(d, x = unit(0.5, "npc"), 
                         y = unit(0.1,"npc"),
                         height=unit(0.8,"npc"),
                         width=unit(0.5, "cm"), size=0.7,
                         margin=unit(1,"mm"), tick.length=0.2*width,
                         pretty.breaks = grid.pretty(range(d)),
                         digits = 2, show.extrema=TRUE,
                         palette = diverging_palette(d), n = 1e2,
                         point.negative=TRUE,   gap =5,
                         interpolate=TRUE,
                         ...){

  ## includes extreme limits of the data
  legend.vals <- unique(round(sort(c(pretty.breaks, min(d), max(d))), digits)) 

  legend.labs <- if(show.extrema)
    legend.vals else unique(round(sort(pretty.breaks), digits)) 

  ## interpolate the colors
  colors <- palette(seq(min(d), max(d), length=n))
  ## 1D strip of colors, from bottom <-> min(d) to top <-> max(d)
  lg <- rasterGrob(rev(colors), # rasterGrob draws from top to bottom
                   y=y, interpolate=interpolate,
                   x=x, just=c("left", "bottom"),
                   width=width, height=height)


  ## box around color strip
  bg <- rectGrob(x=x, y=y, just=c("left", "bottom"),
                 width=width, height=height, gp=gpar(fill="transparent"))

  ## positions of the tick marks
  pos.y <- y + height * rescale(legend.vals)
  if(!show.extrema) pos.y <-  pos.y[-c(1, length(pos.y))]

  ## tick labels
  ltg <- textGrob(legend.labs, x = x + width + margin, y=pos.y,
                          just=c("left", "center"))
  ## right tick marks
  rticks <- segmentsGrob(y0=pos.y, y1=pos.y,
                         x0 = x + width,
                         x1 = x + width - tick.length,
                         gp=gpar())
  ## left tick marks
 lticks <- segmentsGrob(y0=pos.y, y1=pos.y,
                        x0 = x ,
                        x1 = x + tick.length,
                        gp=gpar())

  ## position of the dots
  if(any( d < 0 )){
  yneg <- diff(range(c(0, d[d<0])))/diff(range(d))  * height
  clipvp <- viewport(clip=TRUE, x=x, y=y, width=width, height=yneg,
                     just=c("left", "bottom"))
  h <- convertUnit(yneg, "mm", "y", valueOnly=TRUE)

  pos <- seq(0, to=h, by=gap)
  }
  ## coloured dots
  cg <- if(!point.negative || !any( d < 0 )) nullGrob() else
  pointsGrob(x=unit(rep(0.5, length(pos)), "npc"), y = y + unit(pos, "mm") ,
          pch=21, gp=gpar(col="white", fill="black"),size=unit(size*gap, "mm"), vp=clipvp)
  ## for more general pattern use the following
  ## gridExtra::patternGrob(x=unit(0.5, "npc"), y = unit(0.5, "npc") , height=unit(h,"mm"), 
  ##   pattern=1,granularity=unit(2,"mm"), gp=gpar(col="black"), vp=clipvp)

  gTree(children=gList(lg,  lticks, rticks, ltg, bg, cg),
        width = width + margin + max(stringWidth(legend.vals)), ... , cl="colorbar")
}

grid.colorbar <- function(...){
  g <- colorbarGrob(...)
  grid.draw(g)
  invisible(g)
}

widthDetails.colorbar <- function(x){
 x$width 
}

EDIT: for a pattern fill, you can replace pointsGrob with gridExtra::patternGrob (you could also do it for the tiles of the matrix).

冷情 2025-01-15 16:22:33

我找到了一种方法来手动绘制 levelplot 面板,并在值大于 0.5 的所有单元格上绘制对角线填充图案。

但是,我无法在颜色键图例中绘制相同的图案。经过几个小时的阅读论坛并尝试理解点阵源代码后,我找不到任何线索。也许其他人可以解决这个问题。这是我得到的:

library(lattice)
library(RColorBrewer)
cols <- colorRampPalette(brewer.pal(8, "RdBu"))

data <- Harman23.cor$cov    

fx <- fy <- c()
for (r in seq(nrow(data)))
  for (c in seq(ncol(data)))
  {
    if (data[r, c] > 0.5)
    {
      fx <- c(fx, r);
      fy <- c(fy, c);
    }
  }

diag_pattern <- function(...)
{
  panel.levelplot(...)
  for (i in seq(length(fx)))
  {
    panel.linejoin(x = c(fx[i],fx[i]+.5), y= c(fy[i]+.5,fy[i]), col="black")
    panel.linejoin(x = c(fx[i]-.5,fx[i]+.5), y= c(fy[i]+.5,fy[i]-.5), col="black")
    panel.linejoin(x = c(fx[i]-.5,fx[i]), y= c(fy[i],fy[i]-.5), col="black")   
  }
}      

p <- levelplot(data, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=cols, panel=diag_pattern)
print(p)

在此处输入图像描述

I found a way to manually draw into the levelplot panel and to draw a diagonal fill pattern over all cells with values greater than 0.5

However, I couldn't manage to draw the same pattern in the color key legend. After hours of reading forums and trying to understand the lattice source code, I couldn't get a clue. Maybe someone else could fix that. Here is what I got:

library(lattice)
library(RColorBrewer)
cols <- colorRampPalette(brewer.pal(8, "RdBu"))

data <- Harman23.cor$cov    

fx <- fy <- c()
for (r in seq(nrow(data)))
  for (c in seq(ncol(data)))
  {
    if (data[r, c] > 0.5)
    {
      fx <- c(fx, r);
      fy <- c(fy, c);
    }
  }

diag_pattern <- function(...)
{
  panel.levelplot(...)
  for (i in seq(length(fx)))
  {
    panel.linejoin(x = c(fx[i],fx[i]+.5), y= c(fy[i]+.5,fy[i]), col="black")
    panel.linejoin(x = c(fx[i]-.5,fx[i]+.5), y= c(fy[i]+.5,fy[i]-.5), col="black")
    panel.linejoin(x = c(fx[i]-.5,fx[i]), y= c(fy[i],fy[i]-.5), col="black")   
  }
}      

p <- levelplot(data, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=cols, panel=diag_pattern)
print(p)

enter image description here

天暗了我发光 2025-01-15 16:22:33

在我看来,使用两种以上的图案(例如具有不同密度的 45° 和 135° 定向线)会令人困惑。 (尽管我不知道如何使用点阵来做到这一点。)您可以通过使用灰度来实现可读的模式,请参阅 levelplot() 中的 col.regions 参数

library(RColorBrewer)
cols <- colorRampPalette(brewer.pal(8, "RdBu"))
p <- levelplot(Harman23.cor$cov, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=cols)
# versus all greys
p <- levelplot(Harman23.cor$cov, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=gray.colors)
p <- levelplot(Harman23.cor$cov, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=gray.colors(6), cuts=6)

在此处输入图像描述

Using more than two patterns (e.g. 45° and 135° oriented lines with different densities) would be confusing, IMO. (Notwithstanding the fact that I don't know how we could do that using lattice.) You can achieve a readable pattern by using grey scale, see the col.regions argument in levelplot().

library(RColorBrewer)
cols <- colorRampPalette(brewer.pal(8, "RdBu"))
p <- levelplot(Harman23.cor$cov, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=cols)
# versus all greys
p <- levelplot(Harman23.cor$cov, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=gray.colors)
p <- levelplot(Harman23.cor$cov, scales=list(x=list(rot=45)), 
               xlab="", ylab="", col.regions=gray.colors(6), cuts=6)

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文