Is There a Built-In Way to Do a Logarithmic Color Scale in Ggplot2

Is there a built-in way to do a logarithmic color scale in ggplot2?

Yes! There is a trans argument to scale_fill_gradient, which I had missed before. With that we can get a solution with appropriate legend and color scale, and nice concise syntax. Using p from the question and my_breaks = c(2, 10, 50, 250, 1250, 6000):

p + scale_fill_gradient(name = "count", trans = "log",
breaks = my_breaks, labels = my_breaks)

Sample Image

My other answer is best used for more complicated functions of the data. Hadley's comment encouraged me to find this answer in the examples at the bottom of ?scale_gradient.

Logarithmic color scale in ggplot2 squishes certain legend numbers

Use guide="legend"

p + scale_fill_gradient(name = "count", trans = "log",
breaks = my_breaks, labels = my_breaks, guide="legend")

Check out ?scale_fill_gradient

Sample Image

scale_fill_viridis_c color bar on a log scale

Here's an approach using scales::pseudo_log_trans, which lets us plot 0 but transition to a log scaling beyond 1.

my_breaks <- c(0, 0.01, 0.1, 1, 10, 100)

ggplot(data = my_data, aes(x = sample_name,
y = sample_genus,
fill = sample_abundance)) +
geom_tile() +
scale_fill_viridis_c(breaks = my_breaks, labels = my_breaks,
trans = scales::pseudo_log_trans(sigma = 0.001))

Sample Image

ggplot2: Fix legend for logarithmic color scale

If you pass breaks based on the values of the continuous grouping factor to the breaks and labels arguments of scale_color_gradient, the legend will appear as expected. This works whether you use the default colorbar guide, or the legend guide:

brks2 <- sort(unique(myEffs$PrimeVowelDur))
p + scale_color_gradient(trans="log", breaks=brks2, labels=brks2)
p + scale_color_gradient(trans="log", breaks=brks2, labels=brks2, guide="legend")

How to set a logarithmic scale across multiple ggplot2 contour plots?

You can build a data frame with all the data for all alphas combined, with a column indicating the alpha, so you can facet your graph:

I basically removed the plot[[i]] part, and stacked up the d's created in the former loop:

d = numeric()
for(i in seq_along(alphas)) {
z_table <- sapply(x_vals, my_function, y = y_vals, alpha = alphas[i])

x <- rep(x_vals, each = 100)
y <- rep(y_vals, 100)
z <- unlist(flatten(list(z_table)))
z_rel <- z / min(z)
d <- rbind(d, cbind(x, y, z_rel))}

d = as.data.frame(d)

Then we create the alphas column:

d$alpha = factor(paste("alpha =", alphas[rep(1:3, each=nrow(d)/length(alphas))]),
levels = paste("alpha =", alphas[1:3]))

Then build the log scale inside the contour:

ggplot(data = d, aes(x = x, y = y, z = z_rel)) +
geom_contour_filled(breaks=round(exp(seq(log(1), log(1400), length = 14)),1)) +
facet_wrap(~alpha)

Output:

Sample Image

Using geom_line, how do I get the color aesthetic to be on a log scale?

You can add a continuous colour scale with trans = "log10". Example below:

library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.1.1

ggplot(economics, aes(date, unemploy)) +
geom_line(aes(colour = unemploy)) +
scale_colour_viridis_c(trans = "log10")

Sample Image

Created on 2021-10-27 by the reprex package (v2.0.1)

Logarithmic interpolation with geom_smooth

To fit data to a particular model in geom_smooth, you can use nls. For example, to fit to y ~ a + b * log(x) you could do:

ggplot(data=RawData, aes(x=`Time`, y=`Curing`, col=Grade)) +
geom_point(aes(color = Grade), shape = 1, size = 2.5) +
geom_smooth(method = nls, formula = y ~ a + b * log(x + 0.1),
method.args = list(start = list(a = 1, b = 10)), se = F) +
scale_color_manual(values=c('#f92410','#644196')) +
xlab("Tempo espresso in ore") +
ylab("% Di reticolazione") +
labs(color='') +
theme(legend.justification = "top") +
geom_rug(aes(color = Grade))

Sample Image

However, for these particular data, one seems to get a nice curve with y ~ a * atan(b * x). This is also guaranteed to go through the point [0, 0], which seems like it might be required by your model.

ggplot(data=RawData, aes(x=`Time`, y=`Curing`, col=Grade)) +
geom_point(aes(color = Grade), shape = 1, size = 2.5) +
geom_smooth(method = nls, formula = y ~ a * atan(b * x),
method.args = list(start = list(a = 10, b = 5)), se = F) +
scale_color_manual(values=c('#f92410','#644196')) +
xlab("Tempo espresso in ore") +
ylab("% Di reticolazione") +
labs(color='') +
theme(legend.justification = "top") +
geom_rug(aes(color = Grade))

Sample Image

Manual color scale function for ggplot2

You can play around with scale_fill_gradientn.

I think this gets you pretty close as a starting point:

ggplot(coord, aes(x = Re(coord), y = Im(coord), fill = it))+
geom_raster()+
theme_void()+
coord_equal()+
scale_fill_gradientn(colors = c("red", "orange", "gold", "yellow", "green",
"lightblue", "purple", "black"),
values = c(0, 0.3, 0.35, 0.4, 0.5 ,0.6, 0.99,1))

Sample Image

Standardize color scale across maps

You can create color bins using scale_*_steps functions for ggplot. One way would be to create two vectors for the colors and breaks arguments and supply them for each plot. I used some dummy data to show this. If you don't want categorical bins, you can use scale_fill_gradientn instead.

nc <- read_sf(system.file("gpkg/nc.gpkg", package="sf"))
rng <- 2000:7500
nc$randat <- rng[sample.int(length(rng), nrow(nc))]

colors <- c("yellow","yellow1","yellow2","yellow3","yellow4","green","green1","green2","green3","green4", "forestgreen")
breaks <- seq(2000, 7000, by = 500)
ggplot() +
geom_sf(data=nc, aes(fill=randat)) +
scale_fill_stepsn(colors = colors, breaks=breaks)

Sample Image

Edit If you want a more aesthetically pleasing (traditional) color scale, you need to manually bin your data. The cut function will create the labels based on the break values that you set. Then you can use that as the fill variable.

# create breaks
breaks <- seq(2000, 7500, by = 500)

labs <- seq(2001, 7001, by = 500)
labs[1] <- labs[1] - 1
# create labels to use as fill variable
labs <- paste(labs, 'to', breaks[2:length(breaks)])

# applies labels to bins based on breaks
nc['cat'] <- cut(nc$randat, breaks=breaks, labels = labs)

ggplot() +
geom_sf(data=nc, aes(fill=cat)) +
scale_fill_manual(values=colors)

Sample Image

Plotting in R using stat_function on a logarithmic scale

When you use scale_x_log10() then x values are log transformed, and only then used for calculation of y values with stat_function(). Then x values are backtransformed to original values to make scale. y values remain as calculated from log transformed x. You can check this by plotting values without scale_y_log10(). In plot there is straight line.

ggplot(data.frame(x=1:1e4), aes(x)) +
stat_function(fun = function(x) x) +
scale_x_log10()

If you apply scale_y_log10() you log transform already calculated y values, so curve is plotted.



Related Topics



Leave a reply



Submit