Modify viridis palette in ggplot - r

I'm trying to color a ggplot by a factor that's mostly numerical, like so:
iris %>%
ggplot(aes(Sepal.Length, Sepal.Width, color = cut(Petal.Length, 0:7))) +
geom_point() +
scale_color_viridis_d()
What I would like to do is to special-case the (0,1] value and color that in red but to retain the viridis gradient for the remaining values. I know I could change the color on the fly but I wonder if it's also possible to construct a new discrete color palette that has red as its first color and the gradient thereafter, which would make the code a bit more re-usable.
The more general question is therefore: Can one easily add/remove/edit the colors in an existing discrete color palette?

This is basically the same as #seasmith's answer, except with the addition of saving the palette to a variable to use later. I do this often for explicitly setting a NA color and then using the palette across multiple plots.
Other packages have similar functions to the viridis ones: for example, you can get ColorBrewer palettes from RColorBrewer::brewer.pal, CartoColor palettes from rcartocolor::carto_pal, or any of the ggthemes ones from functions with the same name as the palette.
library(tidyverse)
plasma_pal <- c("red", viridis::plasma(n = 6))
plasma_pal
#> [1] "red" "#0D0887FF" "#6A00A8FF" "#B12A90FF" "#E16462FF" "#FCA636FF"
#> [7] "#F0F921FF"
iris %>%
ggplot(aes(Sepal.Length, Sepal.Width, color = cut(Petal.Length, 0:7))) +
geom_point() +
scale_color_manual(values = plasma_pal)
Created on 2018-04-19 by the reprex package (v0.2.0).

Requires a call to scale_color_manual()
iris %>%
ggplot(aes(Sepal.Length, Sepal.Width, color = cut(Petal.Length, 0:7))) +
geom_point() +
scale_color_manual(values = c("red", viridis::viridis(6)))

Related

Choosing the color of only one of the plotted elements

I'm using ggplot to plot a set of values in R and want to colour them according to their sensor name. However, I'd like to change the colour of one of the sensors (not all of them as they are many). Do you have any suggestions?
I'm going to use the following command:
ggplot(molted1, aes( Duration,value,group=test ))+
geom_point(aes(color=sensor))+
facet_grid(~test,scales = "free") +
theme_bw()+
scale_x_continuous(breaks=pretty_breaks(n=3))+
theme(legend.position = "none",axis.title=element_text(size=11))+labs(x="",y="Temperature \n(°C)")
One option is to map the color to the logical test of sensor == selected and then supply the background and highlight colors to scale_color_manual().
If you want to more than one sensor to get highlighted and show different colors for just those ones, you may want to take a look at the {gghighlight} package which does this nicely.
library(tidyverse)
mtcars %>%
ggplot(aes(disp, mpg)) +
geom_point(aes(color = carb == 4), size = 4) +
scale_color_manual(values = c("grey50", "red")) +
facet_grid(~gear)
Created on 2022-04-08 by the reprex package (v2.0.1)

How do I set color hues for a grouped line chart?

I'd like to set the colors for my ggplot line chart from dark blue to light purple.
I think I might have to use color brewer but I'm not sure the right way to do it
Can I set the high color to some color and the low color to some other color?
iris %>%
ggplot(aes(Sepal.Length, Sepal.Width, group = Species)) +
geom_line()
scale_color_gradient will work for continuous data, but not for factors.
You can use colorRampPalette to brew your own palette which interpolates any number of desired shades between two chosen colors.
There is no color named 'light purple' in R's default colors so I used one that looked close. Try this code:
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 3.6.3
### create color making function
colfunct <- colorRampPalette(c("darkblue", "darkorchid1 "))
### brew desired number of colors, which is 3 for the built-in iris dataset
shades <- colfunct(3)
### plot the data and map color to the factor of interest
ggplot(iris, aes(Sepal.Length, Sepal.Width, color=Species))+
geom_point(shape=1)+
geom_smooth(method = lm, formula = y~x, se=FALSE)+
scale_color_manual(values = shades)
Created on 2020-10-10 by the reprex package (v0.3.0)

How do I change the fill color for a computed variable in geom_bar

I am trying to change the default fill color from blue to green or red.
Here is the code I am using
Top_pos<- ggplot(Top_10, aes(x=reorder(Term,Cs), y=Cs, fill=pvalue)) +
geom_bar(stat = "identity", colour="black") + coord_flip()
Using the above code, I get the following image. I have no problem with this data but I do not know how to change the fill color.
It's easy to confuse scaling the color and scaling the fill. In the case of geom_bar/geom_col, color changes the borders around the bars while fill changes the colors inside the bars.
You already have the code that's necessary to scale fill color by value: aes(fill = pvalue). The part you're missing is a scale_fill_* command. There are several options; some of the more common for continuous scales are scale_fill_gradient or scale_fill_distiller. Some packages also export palettes and scale functions to make it easy to use them, such as the last example which uses a scale from the rcartocolor package.
scale_fill_gradient lets you set endpoints for a gradient; scale_fill_gradient2 and scale_fill_gradientn let you set multiple midpoints for a gradient.
scale_fill_distiller interpolates ColorBrewer palettes, which were designed for discrete data, into a continuous scale.
library(tidyverse)
set.seed(1234)
Top_10 <- tibble(
Term = letters[1:10],
Cs = runif(10),
pvalue = rnorm(10, mean = 0.05, sd = 0.005)
)
plt <- ggplot(Top_10, aes(x = reorder(Term, Cs), y = Cs, fill = pvalue)) +
geom_col(color = "black") +
coord_flip()
plt + scale_fill_gradient(low = "white", high = "purple")
plt + scale_fill_distiller(palette = "Greens")
plt + rcartocolor::scale_fill_carto_c(palette = "Sunset")
Created on 2018-05-05 by the reprex package (v0.2.0).
Personally, I'm a fan of R Color Brewer. It's got a set of built-in palettes that play well together for qualitative, sequential or diverging data types. Check out colorbrewer2.org for some examples on real-ish data
More generally, and for how to actually code it, you can always add a scale_fill_manual argument. There are some built-ins in ggplot2 for gradients (examples here)

Stacked barplot with colour gradients for each bar

I want to color a stacked barplot so that each bar has its own parent colour, with colours within each bar to be a gradient of this parent colour.
Example:
Here is a minimal example. I would like for the color of each bar to be different for color, with a gradient within each bar set by `clarity.
library(ggplot2)
ggplot(diamonds, aes(color)) +
geom_bar(aes(fill = clarity), colour = "grey")
In my real problem, I have many more groups of each: requiring 18 different bars with 39 different gradient colours.
I have made a function ColourPalleteMulti, which lets you create a multiple colour pallete based on subgroups within your data:
ColourPalleteMulti <- function(df, group, subgroup){
# Find how many colour categories to create and the number of colours in each
categories <- aggregate(as.formula(paste(subgroup, group, sep="~" )), df, function(x) length(unique(x)))
category.start <- (scales::hue_pal(l = 100)(nrow(categories))) # Set the top of the colour pallete
category.end <- (scales::hue_pal(l = 40)(nrow(categories))) # set the bottom
# Build Colour pallette
colours <- unlist(lapply(1:nrow(categories),
function(i){
colorRampPalette(colors = c(category.start[i], category.end[i]))(categories[i,2])}))
return(colours)
}
Essentially, the function identifies how many different groups you have, then counts the number of colours within each of these groups. It then joins together all the different colour palettes.
To use the palette, it is easiest to add a new column group, which pastes together the two values used to make the colour palette:
library(ggplot2)
# Create data
df <- diamonds
df$group <- paste0(df$color, "-", df$clarity, sep = "")
# Build the colour pallete
colours <-ColourPalleteMulti(df, "color", "clarity")
# Plot resultss
ggplot(df, aes(color)) +
geom_bar(aes(fill = group), colour = "grey") +
scale_fill_manual("Subject", values=colours, guide = "none")
Edit:
If you want the bars to be a different colour within each, you can just change the way the variable used to plot the barplot:
# Plot resultss
ggplot(df, aes(cut)) +
geom_bar(aes(fill = group), colour = "grey") +
scale_fill_manual("Subject", values=colours, guide = "none")
A Note of Caution: In all honesty, the dataset you have want to plot probably has too many sub-categories within it for this to work.
Also, although this is visually very pleasing, I would suggest avoiding the use of a colour scale like this. It is more about making the plot look pretty, and the different colours are redundant as we already know which group the data is in from the X-axis.
An easier approach to achieve a colour gradient is to use alpha to change the transparency of the colour. However, this can have unintended consequences as transparency means you can see the guidelines through the plot.
library(ggplot2)
ggplot(diamonds, aes(color, alpha = clarity)) +
geom_bar(aes(fill = color), colour = "grey") +
scale_alpha_discrete(range = c(0,1))
I have recently created the package ggnested which creates such plots. It is essentially a wrapper around ggplot2 that takes main_group and sub_group in the aesthetic mapping, where colours are generated for the main_group, and a gradient is generated for the levels of sub_group that are nested within each level of the main_group.
devtools::install_github("gmteunisse/ggnested")
require(ggnested)
data(diamonds)
ggnested(diamonds, aes(main_group = color, sub_group = clarity)) +
geom_bar(aes(x = color))
Another option is to use any custom color palette and simply darken/lighten those depending on the fill category. It can be slightly tricky to get a smooth gradient in each bar, but if you keep the natural order of the data (either appearance in data frame or the factor levels) this is not a big problem.
I am using the colorspace package for this task. The shades package also has the option to darken/lighten colors, but the syntax is slightly longer. It is more suitable for modification of entire palettes without specifying specific colors.
library(tidyverse)
library(colorspace)
## get some random colors, here n colors based on the Dark2 palette using the colorspace package.
## But ANY palette is possible
my_cols <- qualitative_hcl(length(unique(diamonds$color)), "Dark2")
## for easier assignment, name the colors
names(my_cols) <- unique(diamonds$color)
## assign the color to the category, by group
df_grad <-
diamonds %>%
group_by(color) %>%
## to keep the order of your stack and a natural gradient
## use order by occurrence in data frame or by factor
## clarity is an ordered factor, so I'm using a dense rank
mutate(
clarity_rank = dense_rank(as.integer(clarity)),
new_cols = my_cols[color],
## now darken or lighten according to the rank
clarity_dark = darken(new_cols, amount = clarity_rank / 10),
clarity_light = lighten(new_cols, amount = clarity_rank / 10)
)
## use this new color for your fill with scale_identity
## you additionally need to keep your ordering variable as group, in this case
## an interaction between color and your new rank
ggplot(df_grad, aes(color, group = interaction(color, clarity_rank))) +
geom_bar(aes(fill = clarity_dark)) +
scale_fill_identity()
ggplot(df_grad, aes(color, group = interaction(color, clarity_rank))) +
geom_bar(aes(fill = clarity_light)) +
scale_fill_identity()
Created on 2022-07-03 by the reprex package (v2.0.1)

Changing colour of as.factor ggplot in R

ggplot(df, aes(x, y, colour = as.factor(z))) +
geom_point() +
geom_line(data=df,aes(y=predict(lmer(mymodel),df),newdata=df)
x and z are my explanatory variable with z being a factor. I then fit a linear mixed-effect model to my data, df.
How do I change the colour of as.factor ggplot in R? It's giving me RBG but I would like different colours. Your advise is appreciated. Thanks.
I think you are looking for scale_colour_manual of scale_colour_brewer. In the first you can specify the colours manually and in the second you can choose one of the Colorbrewer palettes.
You can also define the colors as the post above suggests and reference the colors by name in the following table r colors for ggplot
scale_color_manual(name="Sex", values=c("dark grey", "black"), labels=c("Males", "Females"))
where the name on the legend will be Sex and the labels will be male and female. Also, in the aes(x=year, y = number, color=sex)
You can look for a good combination of colours in here http://colorbrewer2.org/
You will get the code for the corresponding colour you need (for instance "#2ca25f" as a kind of green or "#000000" as black) and you can add it in your code as following:
ggplot(df, aes(x, y, colour = as.factor(z))) +
geom_point() +
geom_line(data=df,aes(y=predict(lmer(mymodel),df),newdata=df) +
scale_color_manual(values = c("#000000", "#2ca25f", ...)
depending on the number of your z factors.
P.S. you can also write common colour names as "black", "white", etc. instead of the #code.

Resources