Pedr Nton
Pedr Nton

Reputation: 79

colour geom_rect under certain condition

I´ve got the following code:

ggplot(dummy$Crustacean) +
  geom_rect(
    aes(
      xmin = char2num(sites_fct) - 0.4,
      xmax = char2num(sites_fct) + 0.4,
      ymin = ifelse(trophic == "Crustacean", 0.01, 1),
      ymax = summed_tu),
    colour = 'black', alpha =0.7) +
  labs(y= expression("Summed TU"[EC10-QSAR]), x= "Sampling sites")+
  scale_y_log10(limits = c(0.0001, 1)) +
  # Fake discrete axis
  scale_x_continuous(labels = sort(unique(dummy$Crustacean$sites_fct)), breaks = 1:9) +
  # before the dot means vertical plotting
  facet_grid(dummy$Crustacean$metrics_fct ~ dummy$Crustacean$trophic) +
  theme_bw()+
  # facet_grid box colour
  theme(strip.background.x = element_rect(colour = "black", fill = "white"),
        strip.background.y = element_blank(), strip.text.y = element_blank())+
  theme(axis.text.x  = element_text(size=10, margin =margin(0,0,0,0), angle =45, vjust = 1, hjust=1),
        axis.title.y = element_blank(),
        axis.text.y  = element_blank(),
        axis.line.x  = element_line(color = 'black', size=0.5),
        axis.line.y  = element_blank())

which give as uutput the following figure:

enter image description here

I need to change the colour of those boxes y > 0.01 in order to have this desire output:

enter image description here

I found several post about background (quite useful for the future) but I cloud not find something like my example.

Thanks!

Upvotes: 1

Views: 637

Answers (1)

chemdork123
chemdork123

Reputation: 13843

OP, this should probably help you. You're trying to draw what appears to be a column or bar chart. In this case, it's probably best to use geom_col instead of geom_rect. With geom_col you only have to supply an x aesthetic (discrete value), and a y aesthetic for the height of the bar. You have not shared your data, but it seems the x axis is categorical already in your dataset, right?

Here's a reprex:

library(ggplot2)

set.seed(1234)
df <- data.frame(x=LETTERS, y=rnorm(26))

ggplot(df, aes(x,y)) +
  geom_col(
    aes(fill=ifelse(y>0, 'positive', 'negative')),
    color='black', alpha=0.8
  ) +
  scale_fill_manual(name='Value', values=c('positive'='orange', 'negative'='gray'))

enter image description here

What's going on here is that we only have to supply x and y to get the bars in the correct place and set the height. For the fill of each of the bars, you can actually just set the label to be "positive" or "negative" (or whatever your desired label would be) on the fly via an ifelse statement. Doing this alone will result in creating a legend automatically with fill colors chosen automatically. To fix a particular set of colors, I'm setting that manually via scale_fill_manual() and supplying a named vector to the values argument.

In your case, you can probably do something similar for geom_rect. That is, you could just try specifying fill= inside aes() and following a similar manner to here if you want... but I'd recommend switching to use geom_col, as it is most appropriate for what you're doing.

EDIT

As OP indicated in the comment, in the original question on which this is based, geom_rect is required since the bars minimum is not always the same number. The ymin aesthetic changes, so it makes sense to use geom_rect here.

The brute force way is to still use ifelse statements inside aes() for fill. It get's a bit dodgey, but it gets the job done:

ggplot(df) +
  geom_rect(
    aes(
      xmin = char2num(sites) - 0.4,
      xmax = char2num(sites) + 0.4,
      ymin = ifelse(trop == "pt", 0.1, 1),
      ymax = conc,
      fill = ifelse(trop == "pt",
                ifelse(conc > 0.1, 'positive', 'negative'),
                ifelse(conc > 1, 'positive', 'negative'))
    ),
    colour = 'black', alpha = 0.8
  ) +
  scale_y_log10() +
  # Fake discrete axis
  scale_x_continuous(labels = sort(unique(df$sites)),
                     breaks = 1:3) +
  scale_fill_manual(name='Conc', values=c('positive'='orange', 'negative'='gray')) +
  facet_grid(. ~ trop) +
  theme_bw()

enter image description here

To complete the setup, you may want to adjust the order of the items in the legend and avoid some of that kind of icky nested ifelse stuff. In that case, you can always do the checking outside the ggplot call. If you have more than the two values for df$trop, you can consider creating the df$conc_min column via a merge with another dataset, but it works just fine here.

df$conc_adjust <- char2num(df$sites)
df$conc_min <- ifelse(df$trop=='pt', 0.1, 1)
df$status <- ifelse(df$conc > df$conc_min, 'positive', 'negative')

# levels of the factor = the order appearing in the legend
df$status <- factor(df$status, levels=c('positive', 'negative'))

ggplot(df) +
  geom_rect(
    aes(
      xmin = conc_adjust - 0.4,
      xmax = conc_adjust + 0.4,
      ymin = conc_min,
      ymax = conc,
      fill = status
    ),
    colour = 'black', alpha = 0.8
  ) +
  scale_y_log10() +
  # Fake discrete axis
  scale_x_continuous(labels = sort(unique(df$sites)),
                     breaks = 1:3) +
  scale_fill_manual(name='Conc', values=c('positive'='orange', 'negative'='gray')) +
  facet_grid(. ~ trop) +
  theme_bw()

enter image description here

Upvotes: 3

Related Questions