是否可以仅更改1个小平面标题的对齐方式

问题描述

我有一个像这样的多面ggplot:

data(iris)
ggplot(iris,aes(x = Petal.Width,y = Sepal.Length)) +
  facet_grid(. ~ Species) +
  geom_point()

enter image description here

问题:

是否可以仅将第一个构面标签(“ setosa”)向左对齐,而将其他第一个构面标签保持居中?

我对ggplot没有任何运气,所以我尝试转换为gtable(下面的代码),我可以看到我可能需要修改的元素是tableGrb#13-strip-t- 1,但我不确定该怎么做。我尝试将gt$layout$lgt$layout$r的值更改为4(原为5),但这使标题完全脱离了刻面。

pl <- ggplot(iris,y = Sepal.Length)) +
  facet_grid(. ~ Species) +
  geom_point()
gt <- ggplotGrob(pl)

gt$layout[gt$layout$name == 'strip-t-1',c('l','r')] <- c(4,4) # my attempt
grid.newpage()
grid.draw(gt)

有人知道这是否可能吗?

解决方法

您有正确的想法,但没有正确的位置。基本上,您需要执行以下操作:

library('ggplot2')
library('grid')

data(iris)
pl <- ggplot(iris,aes(x = Petal.Width,y = Sepal.Length)) +
  facet_grid(. ~ Species) +
  geom_point()
gt <- ggplotGrob(pl)

gt$grobs[[13]]$grobs[[1]]$children$strip.text.x.top..titleGrob.186$children$GRID.text.184$x <- unit(0.1,'npc')
grid.newpage()
grid.draw(gt)

enter image description here

但这对您不起作用...因为您每次使用titleGrob.xxxGRID.text.xxxgt <- ggplotGrob(pl)都会发生变化,所以它甚至对我也不起作用。

因此,请尝试使用另一种方法,并如您所指出的那样知道您需要编辑的位置(在第一个strip中):

gp <- ggplotGrob(pl)
grid.ls(grid.force(gp))

# layout
#   background.1-13-13-1
#   panel-1-1.8-5-8-5
# ...
#   strip-t-1.7-5-7-5                        <- here
#     strip.1-1-1-1
#       strip.background.x..rect.533
#       strip.text.x.top..titleGrob.525
#         GRID.text.523
#   strip-t-2.7-7-7-7
#     strip.1-1-1-1
#       strip.background.x..rect.533
#       strip.text.x.top..titleGrob.528
#         GRID.text.526
#   strip-t-3.7-9-7-9
#     strip.1-1-1-1
#       strip.background.x..rect.533
#       strip.text.x.top..titleGrob.531
#         GRID.text.529
#   axis-t-1.6-5-6-5
# ...
#   title.3-9-3-5
#   caption.11-9-11-5
#   tag.2-2-2-2

您可以使用gPath来获取路径,而无需事先知道GRID.text.xxx。请注意,在您的示例中,我们仅可以编辑第一个GRID.text,并且如果global = FALSE可以使用,即global = TRUE都可以更改。

g1 <- editGrob(
  grid.force(gp),gPath('GRID.text'),grep = TRUE,global = FALSE,x = unit(0.25,'npc')
)
grid.newpage()
grid.draw(g1)

enter image description here

但是,您可能需要一个非常特定的路径,因此请按照strip-t-1到您的GRID.text(请注意,global = TRUE只会影响一个条带)

g2 <- editGrob(
  grid.force(gp),gPath('strip-t-1','strip','GRID.text'),global = TRUE,x = unit(0.75,'npc')
)
grid.newpage()
grid.draw(g2)

enter image description here

,

这是ggtext包最终应该能够以一般方式执行的操作,但是到目前为止,它的HTML呈现代码太有限了。一个新的渲染引擎正在开发中,该引擎支持更多的CSS,包括CSS选择器,从而可以以通用的方式将格式设置为特定数据值的目标。它还支持您需要左对齐文本的text-align属性。

下面是两个如何工作的示例。将新的渲染引擎集成到ggtext中后,您将不再需要帮助程序代码。

# packages needed
library(ggplot2)
library(dplyr)
library(glue)
library(rlang)
library(sinab)  # remotes::install_github("clauswilke/sinab")

# helper code that will eventually live in the ggtext package
element_html <- function(css = NULL,family = NULL,face = NULL,size = NULL,colour = NULL,fill = NULL,linetype = NULL,linewidth = NULL,hjust = NULL,vjust = NULL,lineheight = NULL,margin = NULL,width = NULL,height = NULL,color = NULL,debug = FALSE,inherit.blank = FALSE) {
  if (!is.null(color))
    colour <- color
  
  # doesn't work with other values at this time
  hjust <- 0
  vjust <- 1
  
  structure(
    list(
      css = css,family = family,face = face,size = size,colour = colour,fill = fill,linetype = linetype,linewidth = linewidth,hjust = hjust,vjust = vjust,lineheight = lineheight,margin = margin,width = width,height = height,debug = debug,inherit.blank = inherit.blank),class = c("element_html","element_text","element")
  )
}

element_grob.element_html <- function(element,label = "",x = NULL,y = NULL,...) {
  if (is.null(label))
    return(ggplot2::zeroGrob())
  
  # for now we ignore hjust and vjust,it doesn't work yet
  hj <- 0
  vj <- 1
  
  css <- element$css %||% ""
  
  html_grob(
    label,x = x,y = y,hjust = hj,vjust = vj,width = element$width,height = element$height,css = css
  )
}


# CSS styling
css <- '
p { text-align: center; padding-top: 2px; }
.setosa { text-align: left; }
'

# plotting code
iris %>%
  mutate(
    # set class attribute to species name
    facet_label = glue('<p class = "{Species}">{Species}</p>')
  ) %>%
  ggplot(aes(x = Petal.Width,y = Sepal.Length)) +
  facet_grid(. ~ facet_label) +
  geom_point() +
  theme(strip.text = element_html(css = css))

# another example with different styling
css <- '
p { text-align: center; padding-top: 2px; font-style: italic; }
.setosa { background-color: #0072B2; color: white; }
.versicolor { background-color: #E69F00; }
.virginica { background-color: #009E73;  color: white; }
'

# plotting code
iris %>%
  mutate(
    # set class attribute to species name
    facet_label = glue('<p class = "{Species}">I. {Species}</p>')
  ) %>%
  ggplot(aes(x = Petal.Width,y = Sepal.Length,color = Species)) +
  facet_grid(. ~ facet_label) +
  geom_point() +
  scale_color_manual(
    values = c(
      setosa = "#0072B2",versicolor = "#E69F00",virginica = "#009E73"
    ),guide = "none"
  ) +
  theme_bw() +
  theme(
    strip.background = element_blank(),strip.text = element_html(css = css)
  )

reprex package(v0.3.0)于2020-09-16创建