Can You Specify Different Geoms for Different Facets in a Ggplot

Can you specify different geoms for different facets in a ggplot?

here is another approach by subsetting data:

ggplot(mtcars, aes(mpg, disp)) + facet_wrap(~cyl) + 
geom_point(data = subset(mtcars, cyl == 4)) +
geom_line(data = subset(mtcars, cyl == 6)) +
geom_text(data = subset(mtcars, cyl == 8), aes(label = gear))

Sample Image

Create a facet plot with different geom representations with same x-axis in R

The quickest fix is just putting the legend to the bottom. But here a solution with patchwork.

Note I add "global" theme options that apply to all plots to the call to patchwork, out of convenience and in order to reduce code. It makes it also much easier to change things when needed.

library(tidyverse)
library(patchwork)

ls_iris <- replicate(3, iris, simplify = FALSE)
names(ls_iris) <- letters[1:3]
plot_data <-
bind_rows(map2( ls_iris, letters[1:3], function(x, y) {
x[["Species"]] <- paste(x[["Species"]], y, sep ="_"); x}), .id = "rep")

## facet boxplot
g1 <- ggplot() + geom_boxplot(data = plot_data, aes(Species, Sepal.Width, group = rep)) +
facet_wrap(rep~., scales = "free_x") +
theme(axis.text.x = element_blank(), axis.title.x = element_blank()) # remove x labels and title

## facet heatmap
g2 <- ggplot() + geom_tile(data = plot_data,
aes(factor(Species), rep, fill=Sepal.Width)) +
scale_fill_continuous(low="white", high="#56B4E9", name="Sepal width") +
facet_wrap(rep~., scales = "free_x") +
theme(axis.text.x=element_text(angle=90, vjust=1, hjust=1),
strip.background = element_blank(),
strip.text = element_blank()) # remove facet strips
g1/g2 &
theme(legend.position = "bottom") # theme elements that are for both plots are more conveniently passed to the patchwork call.

Sample Image

Created on 2020-07-09 by the reprex package (v0.3.0)

Using ggplot within a function with facet and multiple geoms

You'll need to switch to aes_string as you expected and change your facet_wrap code to either take the facets argument as a formula or remove the tilde as in the answers to this question. You'll also need to switch to using filter_, which can be used along with interp from package lazyeval.

library(lazyeval)

Here is your function with the changes I outlined and the resulting plot:

plot_fun <- function(df, x, y, ylab = "y-lab", plot_title = "Title", facets) {
ggplot() +
geom_linerange(aes_string(x = x, ymin = 0, ymax = y), colour = I('blue'),
data = filter_(df, interp(~var > 0, var = as.name(y)))) +
geom_linerange(aes_string(x = x, ymin = y, ymax = 0), colour = I('red'),
data = filter_(df, interp(~var <= 0, var = as.name(y)))) +
facet_wrap(facets) +
labs(x = 'Date', y = ylab, title = plot_title)
}

plot_fun(df, x="Date", y="SRI", facets="SITE")

Sample Image

How do I facet by geom / layer in ggplot2?

A hacky way of doing this is to take the existing data frame and create two, three, as many copies of the data frame you need with a value linked to it to be used for the facet and filtering later on. Union (or rbind) the data frames together into one data frame. Then set up the ggplot and geoms and filter each geom for the desired attribute. Also for the facet use the existing attribute to split the plots.

This can be seen below:

df1 <- data.frame(
graph = "point_plot",
mpg
)
df2 <- data.frame(
graph = "spline_plot",
mpg
)

df <- rbind(df1, df2)

ggplot(df, mapping = aes(x = displ, y = hwy, color = class)) +
geom_point(data = filter(df, graph == "point_plot")) +
geom_smooth(data = filter(df, graph == "spline_plot"), se=FALSE) +
facet_grid(. ~ graph)

Sample Image

R ggplot: facet_grid with different geom_rects for each facet trouble

The answer using tidyr functions is a great solution. You can, of course, achieve the result you want with the reshape2 package you're already familiar with.

The critical element you were missing is that the faceting variable can be taken from multiple data arguments, as long as it has the same name and levels. The function below works with the data as you read it in (you probably want to put the function definition before its first use in your script, though!).

plotAccelerometerDataWithPhasesSuperimposed <- function(acceldf, phasesdf) {

# melt the rows for column left/right in order to facet_wrap on it
acceldf_melted <- melt(acceldf[, c('time_ms', 'Ly', 'Ry')],
id.vars = 'time_ms')

# make the facet variables identical
phasesdf$variable <- factor(phasesdf$side, levels = c('Left', 'Right'),
labels = c('Ly', 'Ry'))

ggplot(acceldf_melted, aes(x=time_ms, y=value)) +

# Phases
geom_rect(data = phasesdf, inherit.aes = FALSE, aes(
xmin = acceldf$time_ms[swingStart],
xmax = acceldf$time_ms[heelStrike] - 1,
ymin = -Inf, ymax = Inf, fill = "Swing"), colour = NA, alpha = 0.3) +
geom_rect(data = phasesdf, inherit.aes = FALSE, aes(
xmin = acceldf$time_ms[toeOff],
xmax = acceldf$time_ms[swingEnd] - 1,
ymin = -Inf, ymax = Inf, fill = "Pre-swing"), colour = NA, alpha = 0.3) +
geom_rect(data = phasesdf, inherit.aes = FALSE, aes(
xmin = acceldf$time_ms[heelStrike],
xmax = acceldf$time_ms[toeOff] - 1,
ymin = -Inf, ymax = Inf, fill = "Stance"), colour = NA, alpha = 0.3) +

# Lines
facet_grid(variable~., labeller = labeller(
variable = c(Ly = "Left", Ry = "Right"))) +
labs(title = "Gait Phases by Accelerometer", x = "time (ms)",
y = "Sensors Values") +
geom_line() +
scale_fill_manual('Phases',
values = c('firebrick2', 'orange', 'steelblue2'),
guide = guide_legend()) +
guides(colour = FALSE) +
theme(legend.direction = "horizontal", legend.position = "bottom",
strip.text.y = element_text(size=16, colour = "blue"))
}

Different geom_rect() objects for facets

So you didn't provide us with labels, and only three rows of the first data set, so what follows is incomplete, but should demonstrate how to get the rect's working:

max_24h_lac_vs_cpet <- ggplot(max_24h_lactate_cpet.long, 
aes(x = First_24h_Lactate_Max,
y = Value))

max_24h_lac_vs_cpet + geom_point() +
facet_wrap( ~ Metric, scales="free_y") +
scale_color_brewer(palette="Set1") +
labs(x = "Max Lactate Value < 24h after surgery (mmol)",
y = "Test Metric Value") +
stat_smooth(method="lm") +
geom_rect(data=thresholds, aes(x = NULL,y = NULL,xmin=xmin, xmax=xmax,
ymin=ymin, ymax=ymax,
alpha=0.1,fill="red"))

You were using $ in the first aes() call. Never do that. Then you need to un-map x and y in the geom_rect layer, since they are inherited from the top level ggplot call. The other option would be to use inherit.aes = FALSE.

How to produce different geom_vline in different facets in R?

Here's how you can put in different geom_vline for different iris species:

ggplot(iris, aes(Sepal.Length, Petal.Length)) + facet_wrap(~Species, scales="free") + geom_point() + 
geom_vline(data=filter(iris, Species=="setosa"), aes(xintercept=5), colour="pink") +
geom_vline(data=filter(iris, Species=="versicolor"), aes(xintercept=6), colour="blue") +
geom_hline(data=filter(iris, Species=="virginica"), aes(yintercept=6), colour="green")

Sample Image



Related Topics



Leave a reply



Submit