Good day!

The client wants the color of the line of the function graph (normal distribution) to be shaded as the gradient of the specified colors.

I use this code to build a graph (ggplot):

p <-ggplot(f_table) + geom_histogram( aes( value, colour = ..x.. ), binwidth = 1, fill = I("white") )+ stat_function(fun = function(x) dnorm(x, mean = mean(f_table$value), sd = sd(f_table$value)) *length(f_table$value), size = 1, colour = "gray" )+ geom_tile( aes( x=seq(1:12), y = -0.1, fill =..x.. ), height = 0.2 ) + scale_x_continuous( breaks = seq(0, 10), expand = c(0,0), limits = c(0.5, 10.5) )+ scale_y_continuous( expand = c(0.01, 0) )+ scale_fill_gradientn( colours = clr )+ scale_colour_gradientn( colours = clr )+ theme_minimal()+ xlab("") + ylab("") + theme ( plot.margin = margin(10, 10, 10, 10) , legend.position = "none" , panel.grid = element_blank() , axis.line.y = element_line(size = 0.5, color = "grey80") , axis.ticks.y = element_line(size = 0.5, color = "grey80") , axis.ticks.length = unit (3, "mm") ) p 

here clr is a vector:

  > clr [1] "#FF0000" "#FFC000" "#5B9BD5" "#00B050" 

I get such a schedule enter image description here

It turned out to decorate the outlines of the histogram bars, but how in ggplot to color the distribution graph line itself with a gradient?

You should get something like this (customer sketch): enter image description here

Thanks in advance for your help!

    2 answers 2

    ggplot2 has recently been able to paint lines, by segments.

    Here is an example of coloring a line by data value.

     library(tidyverse) library(viridis) library(gapminder) gapminder %>% filter(country == "France") %>% ggplot(aes(year, lifeExp, color = lifeExp)) + geom_path(size = 1)+ geom_point(shape = 1, size = 5)+ scale_color_viridis() 

    enter image description here

    More recently, ggplot2 did not know how. I even wrote an issue on github


    In your case, you should probably try to calculate the data for the distribution line outside of ggplot2 , and then display it as normal data.

    • Thank you so much for the tip! But viridis itself is not needed. Made a calculation of the curve, according to your advice separately and draw it with the help of geom_path (data = curve, aes (x = curve $ x, y = curve $ value, color = ..x ..), size = 2, lineend = "round ")`. In this case, scale_colour_gradientn (colors = clr) - colors normally. - Arcady Perla
    • viridis is a recommendation)) In most cases, these palettes work fine (if the answer helped, you can mark it as accepted) - ikashnitsky

    Thanks to the advice above, he calculated the curve separately. In this case, scale_colour_gradientn colors as needed. Summary Code:

     curve <- data.frame( x <-seq(0, 10, by=0.05) ) curve$value <-dnorm(curve$x , mean = mean(f_table$value), sd = sd(f_table$value)) *length(f_table$value) p <-ggplot(f_table) + geom_histogram( aes( value, colour = ..x.. ), binwidth = 1, fill = I("white") )+ geom_path( data = curve, aes( x=curve$x, y=curve$value, colour = ..x.. ), size = 2, lineend = "round" )+ scale_x_continuous( breaks = seq(0, 10), expand = c(0,0), limits = c(0.5, 10.5) )+ scale_y_continuous( expand = c(0.01, 0) )+ scale_fill_gradientn( colours = clr )+ scale_colour_gradientn( colours = clr )+ theme_minimal()+ xlab("") + ylab("") + theme ( plot.margin = margin(10, 10, 10, 10) , legend.position = "none" , panel.grid = element_blank() , axis.line.y = element_line(size = 0.5, color = "grey80") , axis.ticks.y = element_line(size = 0.5, color = "grey80") , axis.ticks.length = unit (3, "mm") , axis.text.y = element_text(size = 15, margin = margin(r=8) ) , axis.text.x = element_text(size = 15, margin = margin(t=8) ) ) p 

    Result: enter image description here