13

Consider a simple ggplot2 graph

library(ggplot2) 
dat <- data.frame(name=c("apple", "orange", "plum"),value=c(3,8,2),outlier=c(FALSE,TRUE,FALSE))
ggplot(dat)+geom_point(aes(x=value,y=name))

enter image description here

Is there a way to modify styles attributes of the axis y labels (say color) conditionally, for example depending on the outlier column in dat?

The result would be something like

enter image description here

On a graph with a large number of items this feature wold greatly improve the graph readability and impact.

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
user2147028
  • 1,281
  • 13
  • 19
  • I don't agree with your last sentence. If you want to highlight "outliers", colour the points. Regarding the question: Yes, it's possible. However, not easily, because ggplot2 was not designed to do this. Thus, you'd probably have to generate the grob and hack away at it. – Roland Jun 06 '14 at 06:48
  • Actually this feature has been requested by our graphic designer. The actual graph is much denser than this simple example, with long labels on the axis. We use the color modification to slightly lighten the names of the non-outlier points. The outlier names pop to the eyes, which is the very aim of the graph. That's fairly effective for communication, really ;) – user2147028 Jun 06 '14 at 08:10
  • Possible duplicate of [this question](http://stackoverflow.com/questions/20609716/changing-format-of-some-axis-labels-in-ggplot2-according-to-condition) – Didzis Elferts Jun 06 '14 at 12:30

2 Answers2

22

A simpler way (IMO) to do this is just create a conditional color vector and parse it into axis.text.y

dat <- data.frame(name=c("apple", "orange", "plum"),value=c(3,8,2),outlier=c(FALSE,TRUE,FALSE))
colvec <- character(dim(dat)[1])
colvec <- ifelse(dat$outlier, "red", "black")

library(ggplot2) 
ggplot(dat) +
geom_point(data = dat, aes(x=value,y=name)) +
theme(axis.text.y = element_text(colour=colvec))

enter image description here

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
  • 1
    Perfect thanks! A little extra if the graph is plotted with a `facet_grid(...,scales="free_y")` this method does not seems to apply anymore as the color vector is recycled through the facets. an idea for that case ? – user2147028 Jun 06 '14 at 14:29
  • That could be a new question I guess – David Arenburg Jun 08 '14 at 09:49
4

I don't think this is as good as colouring the outlier point itself, but you can hack away at the grob:

p <- ggplot(dat)+geom_point(aes(x=value,y=name))
g <- ggplotGrob(p)

#I found this by using str(g) and looking for "axis.text.y.text"
#there is probably a clever way of automating this
g[[1]][[2]]$children$axis$grobs[[1]]$gp$col <- c("grey50", "red", "grey50")

plot(g)

enter image description here

Doing this conditionally is possible using something like c("grey50", "red")[dat$outlier] assuming the row order is as needed. However, I can only reiterate that you probably should create a different graph if you think you need something like this.

Roland
  • 127,288
  • 10
  • 191
  • 288
  • Thanks, that's definitely the way to go. I will work to figure out how to automate the localization of the grob. I am yet not very familiar with the gtable structure. – user2147028 Jun 06 '14 at 08:18
  • 3
    For unconditional plot you could just do `ggplot(dat) + geom_point(data = dat, aes(x=value,y=name)) + theme(axis.text.y = element_text(colour=c("grey50", "red", "grey50")))` – David Arenburg Jun 06 '14 at 08:47