2

Consider this simple example

library(tidyverse)
tibble(x = as.factor(c('good', 'neutral', 'bad')),
       y = as.factor(c('bad', 'neutral', 'bad'))) %>% 
  ggplot(aes(x = x, y = y)) + geom_point()

enter image description here

I would like to put the x labels (good, neutral, bad) in different colored boxes. For instance, good (on both the x and y axis) would be surrounded on a small green box, and so on.

Can I do that in ggplot2?

pogibas
  • 24,254
  • 17
  • 63
  • 100
ℕʘʘḆḽḘ
  • 15,284
  • 28
  • 88
  • 180

4 Answers4

6

Like this?

tibble(x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))) %>%
ggplot(aes(x = x, y = y)) + 
  geom_point() + 
  theme(axis.text.x = element_text(color = c('red', 'blue', 'green')))

Your Plot:

your Plot

EDIT

An alternate pretty Ghetto solution using grid

tibble(x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))) %>%
ggplot(aes(x = x, y = y)) + 
  geom_point()

grid::grid.polygon(x = c(.3,.3,.25,.25), y = c(.07,.04,.04,.07),gp = gpar(col = 'green', fill = 'green', alpha = .5))
grid::grid.polygon(x = c(.525,.525,.575,.575), y = c(.07,.04,.04,.07),gp = gpar(col = 'red', fill = 'red', alpha = .5))
grid::grid.polygon(x = c(.79,.79,.86,.86), y = c(.07,.04,.04,.07),gp = gpar(col = 'blue', fill = 'blue', alpha = .5))

the Ghetto way

Max Teflon
  • 1,607
  • 6
  • 13
  • yes, very close! except that instead of coloring the letters, I would like to have a small colored box around each label. Say a red box for bad, a green for good, a whie for neutral – ℕʘʘḆḽḘ Jun 11 '19 at 12:28
  • We re almost there. Just looking for labels very much like the background `spec_color` in `kable` http://haozhu233.github.io/kableExtra/awesome_table_in_html.html – ℕʘʘḆḽḘ Jun 11 '19 at 12:32
  • thanks! pretty interesting but I do not understand the `grid` step here – ℕʘʘḆḽḘ Jun 11 '19 at 12:50
  • for instance, how could I also get the colored boxes on the y axis? – ℕʘʘḆḽḘ Jun 11 '19 at 12:54
  • Yes, you could. Grid 'understands' the whole plot output as a graphic, without using the axis. X- and Y-coordinates are the absolute places of the axis labels, so you only have to play around with them a little, until your boxes cover your y-labels. It is comparable to finishing your plot and drawing onto it using MS Paint;) – Max Teflon Jun 11 '19 at 13:01
2

Another approach

Create a vector of colors and pass them into axis.text.x() option of theme().

# data
x = as.factor(c('good', 'neutral', 'bad'))
y = as.factor(c('bad', 'neutral', 'bad'))
df<- data.frame(x,y)

# create a vector of colors
mycolors<- c("red","blue","green")
library(ggplot2)
ggplot(df, aes(x = x, y=y))+
  geom_point()+
  theme(axis.text.x = element_text(colour = mycolors))

axis-labels

mnm
  • 1,695
  • 2
  • 15
  • 39
  • same comment as below. We re almost there. Just looking for labels very much like the background `spec_color` in `kable` http://haozhu233.github.io/kableExtra/awesome_table_in_html.html – ℕʘʘḆḽḘ Jun 11 '19 at 12:31
  • @ℕʘʘḆḽḘ have you seen these related posts, [1](https://stackoverflow.com/questions/45123684/how-to-draw-boxes-borders-around-x-or-y-axis-labels), [2](https://stackoverflow.com/questions/31370587/how-can-you-create-a-box-around-an-axis-tick-label-in-ggplot2) – mnm Jun 11 '19 at 12:34
2

Solution using geom_label outside the plot area:

ggplot(data, aes(x, y)) +
  geom_point() +
  geom_label(aes(0.3, y, label = y, fill = y), hjust = 0) +
  geom_label(aes(x, 0.45, label = x, fill = x)) +
  theme_minimal() +
  theme(
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    legend.position = "none"
  ) +
  coord_cartesian(xlim = c(1, 3), ylim = c(1, 2), clip = "off")

enter image description here


Another solution

You should create geom_rect with borders, but without fill and plot them outside the plot area (using coord_cartesian):

library(tidyverse)
data <- tibble(
  x = as.factor(c('good', 'neutral', 'bad')),
  y = as.factor(c('bad', 'neutral', 'bad'))
)
ggplot(data, aes(x, y)) +
  geom_point() +
  # put rects on y-axis
  geom_rect(aes(xmin = 0.1, xmax = 0.45, color = y,
                ymin = as.numeric(y) - 0.1, ymax = as.numeric(y) + 0.1),
            fill = NA, size = 3) +
  # put rects on x-axis
  geom_rect(aes(ymin = 0.3, ymax = 0.4, color = x,
                xmin = as.numeric(x) - 0.15, xmax = as.numeric(x) + 0.15),
            fill = NA, size = 3) +
  # Here it's important to specify that your axis goes from 1 to max number of levels
  coord_cartesian(xlim = c(1, 3), ylim = c(1, 2), clip = "off")

enter image description here

pogibas
  • 24,254
  • 17
  • 63
  • 100
0

One approach could be this:

tibble(x = as.factor(c('good', 'neutral', 'bad')),
       y = as.factor(c('bad', 'neutral', 'bad'))) %>% 
  ggplot(aes(x = x, y = y)) + geom_point()+
  geom_rect(aes(xmin=0.5, xmax=1.5, ymin=-Inf, ymax=Inf), fill="red", alpha=0.1)+
  geom_rect(aes(xmin=1.5, xmax=2.5, ymin=-Inf, ymax=Inf), fill="yellow", alpha=0.1)+
  geom_rect(aes(xmin=2.5, xmax=3.5, ymin=-Inf, ymax=Inf), fill="green", alpha=0.1)

With geom_rect() you can add colored backgrounds:

enter image description here

TobKel
  • 909
  • 5
  • 17
  • ah ! thanks but I mean just the label. say, `bad` is enclosed in a red box but this happens only on the axis. As if we just wanted to have colors for the axis labels, but this time we surround the label (good, bad, neutral) with a tiny colored box instead of coloring the text. Do you see what I mean? – ℕʘʘḆḽḘ Jun 11 '19 at 12:28
  • I don't know how I can put the labels into a colored box. But you can adapt the color of the label text: `+ theme(axis.text.x = element_text(color=c("red","yellow","green")), axis.text.y = element_text(color=c("orange","blue")))` – TobKel Jun 11 '19 at 13:44