【问题标题】:How to make a gradient colour in strip.background in ggplot?如何在ggplot中的strip.background中制作渐变色?
【发布时间】:2019-03-26 10:47:10
【问题描述】:

我尝试在ggplot2() 包的strip.background() 函数的填充参数中创建颜色渐变。

这是我想要的图片:

以及我用来尝试拥有它的代码:

# Charge random data
data('mtcars')

# Create fake variable in order to create title into coloured box
mtcars$tempvar <- "My title"

# Run the ggboxplot
ggboxplot(mtcars, x = "cyl", y = "qsec", 
          color = "cyl", 
          palette = c("#E7B800", "#FC4E07",  "#00AFBB"),
          ylab = "cyl", xlab = "qsec",
          legend = "none") + 

 facet_grid(. ~ tempvar) +
  theme(strip.background = element_rect(fill="darkgreen"),
        strip.text = element_text(size=15, colour="white") )

这给出了:

所以我尝试从scale_color_manual()colorRampPalette(c("yellow", "green")) 创建一个调色板并放入element_rect(),但这不起作用。

我也尝试从谷歌图片上传渐变色背景图片,并将其粘贴到 annotation_custom(rasterGrob(image))like 在这个blog中的正确位置,但这也不起作用。

非常感谢任何有关以适当方式编程的建议。

【问题讨论】:

  • 我怀疑是否有适当的方法来对此进行编程,因为 ggplot(可能是故意的)没有办法进行非数据颜色渐变。但就像所有 ggplot 一样,可能会找到破解或解决方法。
  • 您将能够使用色带制作单独的绘图并将其放置在条带上。会很乏味 - 值得怀疑

标签: r ggplot2 gradient


【解决方案1】:

技术上?这是可以做到的。 (无论是图表垃圾还是良好做法是另一回事......)

p <- ggplot(mtcars, aes(mpg, drat)) + 
  geom_point() + 
  facet_grid(~"facet title") 

# basic demonstration
p +
  theme(strip.background = 
          element_gradient(fill1 = "black", fill2 = "white"))

# with different gradient direction & outline specifications
p +
  theme_minimal() +
  theme(strip.background = 
          element_gradient(fill1 = "brown", fill2 = "salmon",
                           direction = "vertical",
                           color = "white", size = 2,
                           linetype = "dotted"))

# with horizontal / vertical facets in different gradient directions
p + facet_grid("vertical title" ~ "horizontal facet title") +
  theme_classic() +
  theme(strip.background = element_gradient(fill1 = "green", fill2 = "yellow", size = 1),
        strip.background.y = element_gradient(direction = "vertical"))

1。将element_gradient 定义为element_rect 的替代方案:

element_gradient <- function(fill1 = NULL, fill2 = NULL, direction = NULL,
                             colour = NULL, size = NULL,
                             linetype = NULL, color = NULL, inherit.blank = FALSE) {
  if (!is.null(color))  colour <- color
  structure(
    list(fill1 = fill1, fill2 = fill2, direction = direction,
         colour = colour, size = size, linetype = linetype,
         inherit.blank = inherit.blank),
    class = c("element_gradient", "element")
  )
}

element_grob.element_gradient <- function(
  element, 
  fill1 = "white", fill2 = "red", direction = "horizontal", # default: white-red gradient
  x = 0.5, y = 0.5, width = 1, height = 1, colour = NULL, 
  size = NULL, linetype = NULL, ...) {

  # define gradient colours & direction
  if(!is.null(element$fill1)) fill1 <- element$fill1
  if(!is.null(element$fill2)) fill2 <- element$fill2
  if(!is.null(element$direction)) direction <- element$direction  
  image <- colorRampPalette(c(fill1, fill2))(2)  
  if(direction == "horizontal") {
    image <- matrix(image, nrow = 1)
  } else {
    image <- matrix(image, ncol = 1)
  }

  gp <- grid::gpar(lwd = ggplot2:::len0_null(size * .pt), col = colour, lty = linetype)
  element_gp <- grid::gpar(lwd = ggplot2:::len0_null(element$size * .pt), col = element$colour,
                     lty = element$linetype, fill = NA)  
  grid::grobTree(
    grid::rasterGrob(image, x, y, width, height, ...),
    grid::rectGrob(x, y, width, height, gp = utils::modifyList(element_gp, gp), ...))
}

2。强制ggplot 接受element_gradient 而不是element_rect for strip.background / strip.background.x / strip.background.y

# make a copy of ggplot's global variables / settings, & modify its element_tree
ggplot_global.new <- ggplot2:::ggplot_global
ggplot_global.new$element_tree$gradient <- ggplot2:::el_def("element_gradient")
ggplot_global.new$element_tree$strip.background <- ggplot2:::el_def("element_gradient", "gradient")
ggplot_global.new$element_tree$strip.background.x <- ggplot2:::el_def("element_gradient", "strip.background")
ggplot_global.new$element_tree$strip.background.y <- ggplot2:::el_def("element_gradient", "strip.background")

3。强制ggplot 不抱怨它,手动覆盖它的检查:

注意:虽然我通常不喜欢修改包的内部函数(即使它是临时的),但在这种情况下,替代方案将涉及根据现有的未导出函数定义一系列中间函数在ggplot2 包中,并依次修改每个。考虑到所涉及的步骤/功能的数量,我认为这种方法会更加脆弱。

  1. 运行trace(ggplot2:::merge_element.element, edit = TRUE) 并替换
if (!inherits(new, class(old)[1])) {
  stop("Only elements of the same class can be merged", call. = FALSE)
}
    

if (!inherits(new, class(old)[1]) & class(new)[1] != "element_gradient") {
  stop("Only elements of the same class can be merged", call. = FALSE)
}
  1. 运行trace(ggplot2:::validate_element, edit = TRUE) 并替换
else if (!inherits(el, eldef$class) && 
         !inherits(el, "element_blank")) {
  stop("Element ", elname, " must be a ", eldef$class, " object.")
}

else if (!inherits(el, eldef$class) && 
         !inherits(el, "element_blank") && 
         eldef$class != "element_gradient") {
  stop("Element ", elname, " must be a ", eldef$class, " object.")

4。完成后,运行以下命令结束疯狂并恢复正常的ggplot 行为:

ggplot_global.new$element_tree$strip.background <- ggplot2:::el_def("element_rect", "rect")
ggplot_global.new$element_tree$strip.background.x <- ggplot2:::el_def("element_rect", "strip.background")
ggplot_global.new$element_tree$strip.background.y <- ggplot2:::el_def("element_rect", "strip.background")

untrace(ggplot2:::merge_element.element)
untrace(ggplot2:::validate_element)

【讨论】:

  • 同意 "chartjunk or good practice" 标志,但是哇!非常令人印象深刻! +1
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2019-06-04
  • 2022-08-10
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
相关资源
最近更新 更多