ggplot2: continuous and discrete scale in facet - r

I am trying to create a plot where I show two measures for the same set of points, one with a discrete scale and one with a continuous scale. I want to show the plots side-by-side, and getting them into facets would be great. Unfortunately, I can't figure out how to have one color scale in one facet and a different color scale in another.
library(tidyverse)
disc <- tibble(x = rnorm(100), y = rnorm(100), color = sample(1:3, 100, replace = TRUE), model = "discrete")
cont <- tibble(x = rnorm(100), y = rnorm(100), color = rnorm(100, 10), model = "continuous")
# want this to be discrete
ggplot(disc, aes(x = x, y = y, color = factor(color))) +
geom_point() + scale_color_discrete()
# want this to be continuous
ggplot(cont, aes(x = x, y = y, color = color)) +
geom_point() + scale_color_viridis_c()
# This would be prettier!
bind_rows( disc, cont ) %>%
ggplot(aes(x = x, y = y, color = color)) +
geom_point() +
facet_wrap(~model)
Created on 2021-10-16 by the reprex package (v2.0.0)
I realize that this is probably outside the intended use of facet. But I'm having a harder time getting the maps to print side-by-side in a coherent way and thought this could be a more sustainable shortcut.

Just learned about ggnewscale in my searching, and it seems to be easy enough! :
library(tidyverse)
library(ggnewscale)
disc <- tibble(x = rnorm(100), y = rnorm(100), color = sample(letters[1:3], 100, replace = TRUE), model = "discrete")
cont <- tibble(x = rnorm(100), y = rnorm(100), color = rnorm(100, 10), model = "continuous")
ggplot(mapping = aes(x = x, y = y)) +
geom_point(data = disc, aes(color = color)) +
scale_color_discrete("discrete") +
new_scale_color() +
geom_point(data = cont, aes(color = color)) +
scale_color_viridis_c("continuous") +
facet_wrap(~model)
Created on 2021-10-16 by the reprex package (v2.0.0)

Related

Exclude a particular area from geom_smooth fit automatically

I am plotting different plots in my shiny app.
By using geom_smooth(), I am fitting a smoothing curve on a scatterplot.
I am plotting these plots with ggplot() and rendering with ggplotly().
Is there any way, I can exclude a particular data profile from geom_smooth().
For e.g.:
It can be seen in the fit, the fit is getting disturbed and which is not desirable. I have tried plotly_click(), plotly_brush(), plotly_select(). But, I don't want user's interference when plotting this fit, this makes the process much slower and inaccurate.
Here is my code to plot this:
#plot
g <- ggplot(data = d_f4, aes_string(x = d_f4$x, y = d_f4$y)) + theme_bw() +
geom_point(colour = "blue", size = 0.1)+
geom_smooth(formula = y ~ splines::bs(x, df = 10), method = "lm", color = "green3", level = 1, size = 1)
Unfortunately, I can not include my dataset in my question, because the dataset is quite big.
You can make an extra data.frame without the "outliers" and use this as the input for geom_smooth:
set.seed(8)
test_data <- data.frame(x = 1:100)
test_data$y <- sin(test_data$x / 10) + rnorm(100, sd = 0.1)
test_data[60:65, "y"] <- test_data[60:65, "y"] + 1
data_plot <- test_data[-c(60:65), ]
library(ggplot2)
ggplot(data = test_data, aes(x = x, y = y)) + theme_bw() +
geom_point(colour = "blue", size = 0.1) +
geom_smooth(formula = y ~ splines::bs(x, df = 10), method = "lm", color = "green3", level = 1, size = 1)
ggplot(data = test_data, aes(x = x, y = y)) + theme_bw() +
geom_point(colour = "blue", size = 0.1) +
geom_smooth(data = data_plot, formula = y ~ splines::bs(x, df = 10), method = "lm", color = "green3", level = 1, size = 1)
Created on 2020-11-27 by the reprex package (v0.3.0)
BTW: you don't need aes_string (which is deprecated) and d_f4$x, you can just use aes(x = x)

How to make geom_errorbar() the same color as the fill of points when using border customizable pch in ggplot R?

I'm using the special pch (21-25) to make a scatter plot with ggplot since I want the fill of the points to vary with factor levels, but I also want the border of the points to be fixed as black. I wish to add an error bar to each of the points and I want the error bar to be the same color as the fill of the points. However, since I'm fixing the colour aesthetic of points to black and geom_errorbar() uses this to plot the color of the error bars I can't seem to figure out how to get the result I want.
Here is a simple example where I'm getting the undesired result (black color in the error bars):
library(ggplot2)
test <- cbind.data.frame(
x = rnorm(10),
y = rnorm(10),
stdv = sd(rnorm(10)),
fl = c(rep("foo", 5), rep("bar", 5))
)
ggplot(data = test, aes(x = x, y = y, colour = fl, fill = fl, ymin = y - stdv, ymax = y + stdv)) +
geom_point(shape = 21, size = 3) +
scale_colour_manual(values = rep("black", nrow(test))) +
geom_errorbar()
You can try with new_scale_color() from ggnewscale package (for sure this a trick I learnt from #AllanCameron):
library(ggplot2)
library(ggnewscale)
#Data
test <- cbind.data.frame(
x = rnorm(10),
y = rnorm(10),
stdv = sd(rnorm(10)),
fl = c(rep("foo", 5), rep("bar", 5))
)
#Plot
ggplot(data = test, aes(x = x, y = y,
colour = fl,
fill = fl,
ymin = y - stdv,
ymax = y + stdv)) +
geom_point(shape = 21, size = 3) +
scale_colour_manual(values = rep("black", nrow(test))) +
new_scale_color()+
geom_errorbar(aes(color=fl))
Output:
Any reason you're using scale_colour_manual() instead of just using colour = "black"? If your actual example allows you to use that, then, you don't need ggnewscale:
library(ggplot2)
test <- cbind.data.frame(
x = rnorm(10),
y = rnorm(10),
stdv = sd(rnorm(10)),
fl = c(rep("foo", 5), rep("bar", 5))
)
ggplot(data = test, aes(x = x, y = y, colour = fl, fill = fl, ymin = y - stdv, ymax = y + stdv)) +
geom_point(shape = 21, size = 3, colour = "black") +
geom_errorbar()
Created on 2020-12-11 by the reprex package (v0.3.0)

Force size aesthetic to scale to given breaks

I am creating several plots in order to create frames for a gif. It is supposed to show growing points over time. (see plot 1 and 2 - the values increase). Using size aesthetic is problematic, because the scaling is done for each plot individually.
I tried to set breaks with scale_size_area() to provide a sequence of absolute values, in order to scale on 'all values' rather than only the values present in each plot. (no success).
Plot 3 shows how the points should be scaled, but this scaling should be achieved in each plot.
library(tidyverse)
df1 <- data.frame(x = letters[1:5], y = 1:5, size2 = 21:25)
ggplot(df1, aes(x, y, size = y)) +
geom_point() +
scale_size_area(breaks = seq(0,25,1))
ggplot(df1, aes(x, y, size = size2)) +
geom_point() +
scale_size_area(breaks = seq(0,25,1))
df2 <- data.frame(x = letters[1:5], y = 1:5, size2 = 21:25) %>% gather(key, value, y:size2)
ggplot(df2, aes(x, value, size = value)) +
geom_point() +
scale_size_area(breaks = seq(0,25,1))
Created on 2019-05-12 by the reprex package (v0.2.1)
Pass lower and upper bound to limits argument in scale_size_area function:
ggplot(df1, aes(x, y, size = y)) +
geom_point() +
labs(
title = "Y on y-axis",
size = NULL
) +
scale_size_area(limits = c(0, 25))
ggplot(df1, aes(x, y, size = size2 )) +
geom_point() +
labs(
title = "size2 on y-axis",
size = NULL
) +
scale_size_area(limits = c(0, 25))
How about this?
library("ggplot2")
df1 <- data.frame(x = letters[1:5],
y = 1:5)
ggplot(data = df1,
aes(x = x,
y = y,
size = y)) +
geom_point() +
scale_size_area(breaks = seq(1,25,1),
limits = c(1, 25))

Continuous colour of geom_line according to y value

If you look at this
ggplot(mtcars,aes(x=disp,y=mpg,colour=mpg))+geom_line()
you will see that the line colour varies according to the corresponding y value, which is what I want, but only section-by-section. I would like the colour to vary continuously according to the y value. Any easy way?
One possibility which comes to mind would be to use interpolation to create more x- and y-values, and thereby make the colours more continuous. I use approx to " linearly interpolate given data points". Here's an example on a simpler data set:
# original data and corresponding plot
df <- data.frame(x = 1:3, y = c(3, 1, 4))
library(ggplot2)
ggplot(data = df, aes(x = x, y = y, colour = y)) +
geom_line(size = 3)
# interpolation to make 'more values' and a smoother colour gradient
vals <- approx(x = df$x, y = df$y)
df2 <- data.frame(x = vals$x, y = vals$y)
ggplot(data = df2, aes(x = x, y = y, colour = y)) +
geom_line(size = 3)
If you wish the gradient to be even smoother, you may use the n argument in approx to adjust the number of points to be created ("interpolation takes place at n equally spaced points spanning the interval [min(x), max(x)]"). With a larger number of values, perhaps geom_point gives a smoother appearance:
vals <- approx(x = df$x, y = df$y, n = 500)
df2 <- data.frame(x = vals$x, y = vals$y)
ggplot(data = df2, aes(x = x, y = y, colour = y)) +
geom_point(size = 3)
Since ggplot2 v0.8.5 one can use geom_line or geom_path with different lineend options (right now there are three options: round, butt and square). Selection depends on the nature of the data.
round would work on sharp edges (like in given OPs data):
library(ggplot2)
ggplot(mtcars, aes(disp, mpg, color = mpg)) +
geom_line(size = 3, lineend = "round")
square would work on a more continuous variable:
df <- data.frame(x = seq(0, 100, 10), y = seq(0, 100, 10) ^ 2)
ggplot(data = df, aes(x = x, y = y, colour = y)) +
geom_path(size = 3, lineend = "square")
Maybe this will work for you:
library(dplyr)
library(ggplot2)
my_mtcars <-
mtcars %>%
mutate(my_colors = cut(disp, breaks = c(0, 130, 200, 400, Inf)))
ggplot(my_mtcars, aes(x = disp, y = mpg, col = mpg)) +
geom_line() + facet_wrap(~ my_colors, scales = 'free_x')

Wide Range of the same Color in R

Is it possible to create great number of different kinds of "red" color. For better understanding I am expecting following, but instead of grey I desire to have "red" or "red-black".
mypalette <- rev(grey.colors(10000, start = 0.1, end = 0.5, gamma = 4))
plot(1:length(mypalette),1:length(mypalette), col=mypalette, pch=16)
The color packages I know have limited range of colors. Any idea will be appreciated.
If I understand what you want, try colorRampPalette. It returns a function that outputs the requested number of colours between the two you specified.
reds <- colorRampPalette(c("black","red"))
reds(5)
[1] "#000000" "#3F0000" "#7F0000" "#BF0000" "#FF0000"
Here are some ggplot alternatives
library(ggplot2)
df <- data.frame(x = rnorm(100), y = rnorm(100), z = rnorm(100), z2 = factor(1:5))
# colour set by continuous variable
ggplot(data = df, aes(x = x, y = y, colour = z)) +
geom_point() +
scale_colour_gradient(low = "red", high = "white")
library(RColorBrewer)
ggplot(data = df, aes(x = x, y = y, colour = z)) +
geom_point() +
scale_colour_gradientn(colours = brewer.pal(5, "Reds"))
# colour set by discrete variable
ggplot(data = df, aes(x = x, y = y, colour = z2)) +
geom_point() +
scale_colour_brewer(palette = "Reds")

Resources