3

I would like to conditionally alter the color/face/etc of a continuous tick mark label using logic instead of hard coding. For example:

library(tidyverse)
library(viridis)
xx=rpois(1000,lambda = 40)
y=density(xx,n=3600,from=0)

ggplot(data.frame(x = y$x, y = y$y), aes(x, y)) + 
  geom_line() + 
  geom_segment(aes(xend = x, yend = 0, colour = y)) + 
  scale_color_viridis() +
  labs(y='Density',x='Count',colour='Density')+
  geom_vline(xintercept=40,color='red') +
  scale_x_continuous(breaks=c(0,40,seq(25,100,25)),limits=c(0,100))+
  theme(axis.text.x = element_text(face=c('plain','bold',rep('plain',4)),
                                   color=ifelse(y$x==60,'red','black')))

So in my example above, hard coding is seen in the face function and that works (I can do the same thing for color). It's not a big deal here since I only have a few breaks. In future scenarios, though, I may have significantly more breaks or a less simple coloring scheme needed for my axes. Is there a more efficient solution to create this labeling based on conditional logic? My first attempt is seen in color function but that does not work . The issue is identifying the object to use in the logical statement. Maybe there is a behind the scenes variable I can call for the breaks (similar to using ..level.. for a density plot). If that's the case, bonus points if you can teach me how to find it/figure that out on my own

4
  • "Behind the scenes" variables like ..level.. are generally only available inside aes(). Commented Mar 2, 2018 at 20:14
  • 2
    I don't think you can do it programmatically within theme. But if you already have specified a breaks vector, just use it to create also the face vector in advance. See also: Change color of specific tick in ggplot2 Commented Mar 2, 2018 at 20:15
  • Thanks! These helped out a lot. I took your advice and defined my breaks vector before the plot. I was then able to use the ifelse logic within theme... i.e. ifelse(breaks==40,'red','black') I'm not sure it's any better than defining the color (or face) vector before the plot like the breaks vector but I thought it was interesting to see it work. Commented Mar 2, 2018 at 20:49
  • @godzilla you should write your solution as an answer and accept it to mark this question answered. It's an interesting question! :) Commented Mar 3, 2018 at 22:14

1 Answer 1

1

Quick thanks to Djork for teaching me some QnA etiquette...

I was able to solve this problem by defining my break points outside of ggplot and then using ifelse logic within the theme function to create my desired outcome. The updated (and working) example of my original code is below:

library(tidyverse)
library(viridis)
xx=rpois(1000,lambda = 40)
y=density(xx,n=3600,from=0)

med_x=median(xx)
breakers = c(seq(0,100,25),med_x)

ggplot(data.frame(x = y$x, y = y$y), aes(x, y)) + 
  geom_line() + 
  geom_segment(aes(xend = x, yend = 0, colour = y)) + 
  scale_color_viridis() +
  labs(y='Density',x='Count',colour='Density')+
  geom_vline(xintercept=40,color='red') +
  scale_x_continuous(breaks=breakers,limits=c(0,100))+
  theme(axis.text.x = element_text(face=ifelse(breakers==med_x,'bold','plain'),
                                   color=ifelse(breakers==med_x,'red','black')))

I haven't tried this on more complicated logic yet but I assume that this approach will work across all logical formatting.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.