0

I need to make a barplot with gradual colors from green to red. I have two variables: the first variable takes values between 0.2 and 0.61, the second variable takes values between 0.1 and 0.41. I wrote the following code:

d <- data.frame(x = 1:2, y= c (0.61, 0.41))
vals <- lapply(d$y, function(y) seq(0.1, y, by = 0.0001))
y <- unlist(vals)
mid <- rep(d$x, lengths(vals))
d2 <- data.frame(x = mid - 0.4,
             xend = mid + 0.4,
             y = y,
             yend = y)

ggplot(data = d2, aes(x = x, xend = xend, y = y, yend = yend, color = y)) +
      geom_segment(size = 2) + theme(plot.title = element_text(hjust = 0.5, size=20),legend.text=element_text(size=13))+
      scale_color_gradient2(low = "green", mid = "yellow", high = "red", 
                    midpoint = .35)+ 
      theme(axis.text.y=element_blank(),  
            axis.ticks.y=element_blank(), 
            panel.background = element_blank(),
            axis.line.x = element_line(color="black", size = 1),
            axis.line.y = element_line(color="black", size = 1),
            axis.text.x=element_text(size=15,hjust=0.1))+ylab("")+xlab("")+
      scale_y_continuous(breaks = c(0.1, .35,0.61), 
                 labels = c('A ','B ','C '), limits = c(0.1, .61))+coord_flip()

However, it is not the result I want. I would like the bars to have the same length. In particular, I would like the first bar at the top to reach C with the color orange. Also, I would like the second bar at the bottom to have a lighter green color since in A the first variable takes value 0.2 (and not 0.1).

I hope someone can help me! Thank you for your cooperation.

MacUser
  • 63
  • 6
  • "X takes values between 0.2 and 0.61, Y takes values between 0.1 and 0.41" In `d2`, it looks like y varies from 0.1 to 0.61, based on `range(d2$y)`, and x is either 0.6 or 1.6. – Jon Spring Mar 07 '23 at 22:26
  • In this case, x is not the variable. It is introduced to construct the 2 bars – MacUser Mar 07 '23 at 22:39
  • It seems like the plot is showing your data, but you want the data to be something different? Can you add more to explain which step isn't what you expect, perhaps using a simpler example? For instance, if I replace your 2nd line with `vals <- lapply(d$y, function(y) seq(0.1, y, by = 0.1))` and then run a simpler version of `ggplot(data = d2, aes(x = y, xend = yend, y = x, yend = xend, color = y)) + geom_segment(size = 2)`, I can see how the bars are different widths, using only 10 values instead of 8202. – Jon Spring Mar 07 '23 at 22:47
  • related https://stackoverflow.com/questions/48210231/creating-a-vertical-color-gradient-for-a-geom-bar-plot?noredirect=1&lq=1 – tjebo Mar 07 '23 at 22:55
  • It is probably not clear what I want to achieve. Simplifying the problem, assuming we have this matrix: A = matrix( c('X', 'Time1', 0.2, 'X', 'Time2', 0.4, 'X', 'Time3', 0.6, 'Y', 'Time1', 0.1, 'Y', 'Time2', 0.25, 'Y', 'Time3', 0.4 ), nrow = 6,ncol = 3, byrow = TRUE) colnames(A) = c("variable", "group", "value"). I would like to have a barplot with the three Time steps on the X-axis and the two variables (X, Y) on the Y-axis. I would like the bars to be the same length with a color varying from green (in Time1) to red (in Time3) with different color intensity. I hope it is clearer now. – MacUser Mar 07 '23 at 23:05

1 Answers1

2

At the moment, the colours and the length of the bars are mapped to the same variable. I think you need to separate these out. The colour should be some re-scaled, transformed version of the x-coordinates that create the bars.

A more generic example, using bars between 0 and 1, and data for X and Y in different ranges:

library(tidyverse)
plot_data <- tibble(
  x = rep(seq(0, 1, length.out = 1000), 2),
  xend = rep(seq(0, 1, length.out = 1000), 2),
  y = rep(rep(-1, 1000), 2),
  yend = rep(rep(1, 1000), 2),
  variable = c(rep("X", 1000), rep("Y", 1000)),
  col = c(seq(0.2, 0.6, length.out = 1000), seq(0.3, 0.9, length.out = 1000)),
)

plot_data |> 
  ggplot() +
  geom_segment(mapping = aes(x = x, 
                             xend = xend, 
                             y = y, 
                             yend = yend,
                             colour = col)) +
  facet_wrap(~variable, ncol = 1) +
  scale_x_continuous(breaks = c(0, 0.5, 1), 
                     labels = c('A', 'B', 'C')) +
  scale_color_gradient2(low = "green",
                        mid = "yellow",
                        high = "red", 
                        midpoint = 0.5,
                        limits = c(0, 1))+ 
  theme(strip.background = element_blank(),
        legend.position = "none")

enter image description here

You'll need to be careful with the legend, to make sure the values make sense (or just use low, medium, high labels instead)

nrennie
  • 1,877
  • 1
  • 4
  • 14
  • Thank you very much! Certainly the legend I have to reset it..I sincerely thank you for your help! – MacUser Mar 08 '23 at 09:01