【问题标题】:Handle ggplot2 axis text face programmatically以编程方式处理 ggplot2 轴文本面
【发布时间】:2018-04-07 00:31:26
【问题描述】:

(x-发布到community.rstudio.com

我想知道是否可以通过编程方式更改ggplot2 中的轴文本,或者是否有一些本地方法可以在ggplot2 中执行此操作。在这个代表中,我的想法是我想将变量y 的轴文本加粗,该变量的绝对值x 超过1.5。我可以通过theme()手动添加,效果很好:


library(ggplot2)
library(dplyr)
library(forcats)

set.seed(2939)
df <- data.frame(x = rnorm(15), y = paste0("y", 1:15), group = rep(1:3, 5))

df <- mutate(df, big_number = abs(x) > 1.5, face = ifelse(big_number, "bold", 
  "plain"))

p <- ggplot(df, aes(x = x, y = fct_inorder(y), col = big_number)) + geom_point() + 
  theme(axis.text.y = element_text(face = df$face))

p

没有分面的图 1

但是,如果我通过group 来区分它,y 会被重新排序,ggplot2 不知道face 是如何连接到dfy,所以它只是以相同的顺序加粗第一个情节。

p + facet_grid(group ~ .)

带有刻面的图 2

如果我为每个人使用不同的比例,情况会更糟。

p + facet_grid(group ~ ., scales = "free")

带有刻面和不同尺度的图 3

你怎么看?有没有一种通用的方法可以在这里始终如一地处理这个问题?

【问题讨论】:

标签: r ggplot2 expression


【解决方案1】:

想法:不要更改主题,更改 y 轴标签。使用if/else 条件为每个y 创建一个调用,并使用parse 对其进行解析。

不是最优雅的解决方案(使用 for 循环),但有效(需要循环,因为 bquote 不适用于 ifelse)。尝试使用多个表达式时,我总是感到困惑(更多关于 here)。

代码:

# Create data
library(tidyverse)
set.seed(2939)
df <- data.frame(x = rnorm(15), y = paste0("y", 1:15), group = rep(1:3, 5)) %>%
    mutate(yF = fct_inorder(y),
           big_number = abs(x) > 1.5)

# Expressions for y-axis
# ifelse doesn't work
# ifelse(df$big_number, bquote(bold(1)), bquote(plain(2)))
yExp <- c() # Ignore terrible way of concatenating 
for(i in 1:nrow(df)) {
    if (df$big_number[i]) {
        yExp <- c(yExp, bquote(bold(.(as.character(df$yF[i])))))
    } else {
        yExp <- c(yExp, bquote(plain(.(as.character(df$yF[i])))))
    }
}

# Plot with facets
ggplot(df, aes(x, yF, col = big_number)) + 
    geom_point() +
    scale_y_discrete(breaks = levels(df$yF), 
                     labels = parse(text = yExp)) +
    facet_grid(group ~ ., scales = "free")

结果:

【讨论】:

  • 有趣!我尝试了一种类似的方法,在标签中使用一个函数来处理它。我认为使用比例标签可能会尽可能接近。
【解决方案2】:

受@PoGibas 启发,我还使用了scale_y_discrete() 中的一个函数,它也可以。

bold_labels <- function(breaks) {
  big_nums <- filter(df, y %in% breaks) %>%
    pull(big_number)
  labels <- purrr::map2(
    breaks, big_nums,
    ~ if (.y) bquote(bold(.(.x))) else bquote(plain(.(.x)))
  )
  parse(text = labels)
}

ggplot(df, aes(x, fct_inorder(y), col = big_number)) + 
    geom_point() +
    scale_y_discrete(labels = bold_labels) +
    facet_grid(group ~ ., scales = "free")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    相关资源
    最近更新 更多