使用不同颜色自定义ggplot2轴标签

66

我使用ggplot2创建了一个基本的柱形图。y变量包含正值和负值,大约一半向量值为负。我想自定义坐标轴标签,使得当相应的x因子的y值为负时,其标签为红色。以下是一个可再现的例子:

#Create data
x <- c("a","b","c","d","e","f")
y <- c("10", "9","-10","11","-3","-15")
data <- data.frame(x, y)
data$y <- as.numeric(as.character(data$y))

data$category <- ifelse(as.numeric(data$y)<0, 0, 1)
data$category <- as.factor(data$category)

#Graph
library(cowplot) #theme
library(ggplot2)

ggplot(data, aes(x=x, y=y)) + 
  geom_bar(stat = "identity", aes(fill=category)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(axis.text.x = element_text(colour = "black"))

enter image description here

我需要一种方法来将 "c", "e" 和 "f" 的标签颜色更改为我选择的颜色。 我尝试切换 theme(aes(axis.text.x=element_text(colour=Air_pricier))) 但出现了错误。

4个回答

114
你可以将颜色向量提供给theme()中的axis.text.x选项:
a <- ifelse(data$category == 0, "red", "blue")

ggplot(data, aes(x = x, y = y)) + 
    geom_bar(stat = "identity", aes(fill = category)) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1, colour = a))

输入图像描述


3
有没有更自动的方式来设置坐标轴标签颜色以匹配图例颜色?特别是在有超过两个类别时,这些类别除了名称之外很难区分。 - andemexoax
1
@andemexoax 使用 mystrings <- c("vector","of","categories") 然后 a <- ifelse(data$category %in% mystrings, "red", "blue") - Justapigeon
“@Sumedh”,如果我只想让标签以不同的颜色设置,该怎么办? - mjs
15
这很好,但是对我生成了一个警告信息:“警告消息:传递给“element_text()”的向量化输入不被官方支持。结果可能无法预料或在未来的ggplot2版本中发生更改。” - Mark Neal
我也尝试了与 facet_wrap 结合使用,看起来必须在所有小面板中使用相同的颜色方案;即不同的小面板不能有不同的颜色集。 - S. Robinson
4
可以通过使用 ggtext::element_markdown 替代 element_text 来避免警告信息 Warning message: Vectorized input to "element_text()" is not officially supported. Results may be unexpected or may change in future versions of ggplot2.,因为 ggtext::element_markdown 官方支持向量化输入。 - Matthias Munz

25

我也收到了@Mark Neal评论中提到的警告消息,这让我很紧张。以下是使用ggtext包的替代方法。你可以在x轴的类别中用<span>来包装,并指定所需的颜色,然后在主题中使用element_markdown

library(ggtext)
library(tidyverse)

data %>%
  mutate(x.label = paste("<span style = 'color: ",
                         ifelse(y > 0, "black", "red"),
                         ";'>",
                         x,
                         "</span>", sep = ""),
         x.label = fct_reorder(x.label, as.character(x))) %>%
  ggplot(aes(x=x.label, y=y)) + 
  geom_bar(stat = "identity", aes(fill=category)) +
  theme(axis.text.x = element_markdown(angle = 45, hjust = 1))

在此输入图片描述


有没有其他替代方案可以使用ggplot2标准动词(而不使用扩展,如ggtext)? - A. Kassambara
并没有我能找到的。但如果有标准的ggplot2解决方案,我很乐意使用它! - A. S. K.
2
这个很好用。你也可以在scale_x_discrete的标签中定义它,这样就不必更改数据中的x值。你还可以使用glue模板在离散比例尺中创建标签,以获得最大的灵活性和便利性。 - snaut
1
我添加了一个答案,它创建了两个图表(一个包含图形,一个包含标签),并将它们合并在一起。这样,标签可以使用ggplot2提供的"图形语法"来创建。 - undefined

6

在a-s-k的答案基础上,我使用了Glue模板和离散比例尺,使其更加灵活。通过这个选项,您不必更改数据,只需要在比例尺中定义一个标签生成器即可完成所有操作。如果您想在许多相似但使用不同数据的图中着色x轴,则这非常方便。

(在原始问题的情况下,颜色取决于更多的数据,而不仅仅是x值,但我想这对某些用户仍然非常有用。)

library(ggtext)
library(tidyverse)
library(glue)

#Create data
x <- c("a","b","c","d","e","f")
y <- c("10", "9","-10","11","-3","-15")
data <- data.frame(x, y)
data$y <- as.numeric(as.character(data$y))

data$category <- ifelse(as.numeric(data$y)<0, 0, 1)
data$category <- as.factor(data$category)

# create the labels 
my_labels <- glue_data(
  data, 
  "<span style='color: {if_else(category==0, 'red', 'blue')}'>{x}</span>"
  )
names(my_labels) <- data$x

# plot as you normally would
# use element_markdown as axis.text.x
# and the labels defined before as labels in a discrete scale
ggplot(data, aes(x=x, y=y)) + 
  geom_bar(stat = "identity", aes(fill=category)) +
  theme(
    axis.text.x = element_markdown(angle = 45, hjust = 1)
  ) + 
  scale_x_discrete(labels=my_labels)

2
一个替代方案是将标签创建为单独的绘图对象,并使用cowplot或patchwork等软件包将它们组合在一起。
#Create data
x <- c("a","b","c","d","e","f")
y <- c("10", "9","-10","11","-3","-15")
data <- data.frame(x, y)
data$y <- as.numeric(as.character(data$y))

data$category <- ifelse(as.numeric(data$y)<0, 0, 1)
data$category <- as.factor(data$category)

# Base plot
library(ggplot2)

pl_base <-
  data |>
  ggplot(aes(x = x))

# Graph
pl_points <-
  pl_base +
  geom_bar(stat = "identity", aes(y = y, fill = category)) +
  theme(plot.margin = unit(c(0,0,0,0), "lines"),
        axis.title.x = element_blank(),
        axis.text.x = element_blank())

# x axis labels
pl_xlab <- pl_base +
  geom_text(aes(label = x, color = category), y = 0, size = 3) +
  scale_y_continuous(expand = c(0, 0), limits = c(0, 0)) +
  #guides(color = "none") + # uncomment to remove the extra legend
  theme_void()

# Combine with patchwork
library(patchwork)
pl_final <-
  pl_points +
  pl_xlab +
  plot_layout(ncol = 1,
              heights = c(NA, 0.07),
              guides = "collect")

# Combine with cowplot
library(cowplot)
pl_final <-
  plot_grid(pl_points,
            pl_xlab,
            ncol = 1,
            align = "hv",
            axis = "b",
            rel_heights = c(1, 0.07))

pl_final

ggplot2 with patchwork output

这是非常灵活的,但在改变最终绘图输出的宽度/高度时,正确定位标签可能会有困难。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接