0

I have 3 numerical vectors of length 45 called omega_S, omega_B and omega_C. The length 45 represents the age from 1 to 45. Can someone help me create a graph similar to this one using ggplot2:

1

These are the vectors:

omega_S<-c(0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1)

omega_B<-c(1.12926243 ,1.11859126 ,1.10754331 ,1.09610527, 1.08426335 ,1.07200332, 1.05931039, 1.04616928, 1.03256418, 1.01847869, 1.00389586 ,0.98879812, 0.97316729 ,0.95698455, 0.94023042, 0.92288471, 0.90492654 ,0.88633429, 0.86708556 ,0.84715717 ,0.82652514 ,0.80516460 ,0.78304984, 0.76015424, 0.73645021, 0.71190921 ,0.68650169, 0.66019706, 0.63296364, 0.60476862, 0.57557807, 0.54535683, 0.51406850, 0.48167542, 0.44813856 ,0.41341755, 0.37747057, 0.34025433, 0.30172403 ,0.26183325,
 0.22053397, 0.17777645, 0.13350921 ,0.08767892, 0.04023042)

omega_C<-1-omega_B-omega_S

2 Answers 2

1

A data.table solution where the curves stack. I changed omega_C limit to be 2, so we don't have negative values. Take note that this apparently doesn't give the same plot as the solution you accepted if you had put omega_C <- 2 - omega_B - omega_S.

omega_S<-c(0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1)

omega_B<-c(1.12926243 ,1.11859126 ,1.10754331 ,1.09610527, 1.08426335 ,1.07200332, 1.05931039, 1.04616928, 1.03256418, 1.01847869, 1.00389586 ,0.98879812, 0.97316729 ,0.95698455, 0.94023042, 0.92288471, 0.90492654 ,0.88633429, 0.86708556 ,0.84715717 ,0.82652514 ,0.80516460 ,0.78304984, 0.76015424, 0.73645021, 0.71190921 ,0.68650169, 0.66019706, 0.63296364, 0.60476862, 0.57557807, 0.54535683, 0.51406850, 0.48167542, 0.44813856 ,0.41341755, 0.37747057, 0.34025433, 0.30172403 ,0.26183325,
           0.22053397, 0.17777645, 0.13350921 ,0.08767892, 0.04023042)

omega_C<- 2

library(ggplot2)
library(data.table)

DT <- data.table(omega_S = omega_S, omega_B = omega_B, omega_C = omega_C)

DT[, c('omega_S_start', 'omega_B_start', 'omega_C_start', 'age') := .(0, omega_S, omega_B, .I) ]

DT <- melt(DT, id.vars = c('omega_S', 'omega_B', 'omega_C', 'omega_S_start', 'omega_B_start', 'omega_C_start', 'age'),
           measure.vars = list(1:3, 4:6) , variable.name = 'type', value.name = c('value_max', 'value_min'))

DT <- copy(DT[, c('type', 'value_min', 'value_max', 'age')])
DT[, type := fcase(type == 1, 'omega_S',
                   type == 2, 'omega_B',
                   type == 3, 'omega_C')]


DT %>% ggplot() +
  geom_ribbon(aes(x = age, ymin = value_min, ymax = value_max, fill = type))

plot

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

2 Comments

In this solution the curves don't stack. So the plot shows the actual values of those omegas u passed as a vector. You could do omega_B <- omega_B + omega_S right after declaring omega_B and have the same results as the great solution from @Stibu below.
Hey, thank you so much for the help! This is exactly what I wanted. Indeed, my results are different to the graph I provided, but that was merely an example. The data isn't the same!
0

You can use geom_area() with position = "stack" in order to stack the areas on top of each other. This requires a few preparation steps to the data.

This defines your vectors as columns in a tibble. Note that (following daniellga) I choose omega_Csuch that the three variables add to 2, since omega_B is sometimes larger than 1.

library(tidyverse)
df <- tibble(omega_S = c(0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1 ,0.1),
             omega_B = c(1.12926243 ,1.11859126 ,1.10754331 ,1.09610527, 1.08426335 ,1.07200332, 1.05931039, 1.04616928, 1.03256418, 1.01847869, 1.00389586 ,0.98879812, 0.97316729 ,0.95698455, 0.94023042, 0.92288471, 0.90492654 ,0.88633429, 0.86708556 ,0.84715717 ,0.82652514 ,0.80516460 ,0.78304984, 0.76015424, 0.73645021, 0.71190921 ,0.68650169, 0.66019706, 0.63296364, 0.60476862, 0.57557807, 0.54535683, 0.51406850, 0.48167542, 0.44813856 ,0.41341755, 0.37747057, 0.34025433, 0.30172403 ,0.26183325,
                       0.22053397, 0.17777645, 0.13350921 ,0.08767892, 0.04023042),
             omega_C = 2 - omega_B - omega_S,
             age = 1:45)

In order to plot the three variables with ggplot, we need to put the data in a different shape. This is a typical step for plots with ggplot(): Every property of the plot must depend on a variable, i.e., a column, in your data frame. Since you want to have different colour for omega_C, omega_B, and omega_S, you need a column that tells for each data point, to which of the three variables it belongs. This can be done with pivot_longer() from the tidyverse package, which we use to write those values in a column type. In addition, we must convert that column into a factor in order to plot the three areas in the expected order.

plot_data <- pivot_longer(df, cols = -"age",
                          names_to = "type") %>%
  mutate(type = factor(type, levels = paste0("omega_", c("C", "B", "S"))))

The plot is then created as follows:

ggplot(plot_data, aes(x = age, y = value, fill = type)) +
  geom_area(position = "stack")

enter image description here

Note that geom_area() is only added once. Because type is mapped on fill, an area is drawn for every value of type. Using position = "stack" tells ggplot to draw the areas on top of each other.

3 Comments

Just be careful because when you stack you sum those values, for example when you stack the green curve above the blue, the maximum value of the green curve will be summed by 0.1. That's the reason there's a little difference between your solution and mine. Your solution is, ofc, fine, it all depends on what values OP wants to be plotted.
@daniellga You are right of course and this is exactly what stacking is for. It is possible to plot the areas on top of each other using position = "identity". The right choice depends, as you rightly point out, on OP's goal and the shape of the input data. Two aspects of the question indicate that stacking might be what OP wants: 1. the example plot shows percentages where stacking would be a natural choice; 2. the three variables are defined such that their sum takes a constant value (while you need to define omega_S as constant).
Hi @Stibu, thank you for the solution and the detailed explanation! ggplot is new to me so the description is very helpful! Thanks to everyone who offered an answer, what a great community!

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.