Ggplot2 Change Axis Limits For Each Individual Facet Panel

Setting individual axis limits with facet_wrap and scales = free in ggplot2

Here's some code with a dummy geom_blank layer,

range_act <- range(range(results$act), range(results$pred))

d <- reshape2::melt(results, id.vars = "pred")

dummy <- data.frame(pred = range_act, value = range_act,
variable = "act", stringsAsFactors=FALSE)

ggplot(d, aes(x = pred, y = value)) +
facet_wrap(~variable, scales = "free") +
geom_point(size = 2.5) +
geom_blank(data=dummy) +
theme_bw()

Sample Image

ggplot2 change axis limits for each individual facet panel

preliminaries

Define original plot and desired parameters for the y-axes of each facet:

library(ggplot2)
g0 <- ggplot(mpg, aes(displ, cty)) +
geom_point() +
facet_grid(rows = vars(drv), scales = "free")

facet_bounds <- read.table(header=TRUE,
text=
"drv ymin ymax breaks
4 5 25 5
f 0 40 10
r 10 20 2",
stringsAsFactors=FALSE)

version 1: put in fake data points

This doesn't respect the breaks specification, but it gets the bounds right:

Define a new data frame that includes the min/max values for each drv:

ff <- with(facet_bounds,
data.frame(cty=c(ymin,ymax),
drv=c(drv,drv)))

Add these to the plots (they won't be plotted since x is NA, but they're still used in defining the scales)

g0 + geom_point(data=ff,x=NA)

This is similar to what expand_limits() does, except that that function applies "for all panels or all plots".

version 2: detect which panel you're in

This is ugly and depends on each group having a unique range.

library(dplyr)
## compute limits for each group
lims <- (mpg
%>% group_by(drv)
%>% summarise(ymin=min(cty),ymax=max(cty))
)

Breaks function: figures out which group corresponds to the set of limits it's been given ...

bfun <- function(limits) {
grp <- which(lims$ymin==limits[1] & lims$ymax==limits[2])
bb <- facet_bounds[grp,]
pp <- pretty(c(bb$ymin,bb$ymax),n=bb$breaks)
return(pp)
}
g0 + scale_y_continuous(breaks=bfun, expand=expand_scale(0,0))

The other ugliness here is that we have to set expand_scale(0,0) to make the limits exactly equal to the group limits, which might not be the way you want the plot ...

It would be nice if the breaks() function could somehow also be passed some information about which panel is currently being computed ...

ggplot2 change date axis limits for each individual facet panel using facetscales package

I'm no expert in computing on the language, but as you mentioned, the dates weren't being evalued as proper dates. The error messages seemed to suggest that the dates were being interpreted as the mathematical expression 2014 - 8 - 12 (= 1994). To fix this, I've moved the as.Date() function outside the brackets and put single quotation marks around the brackets. Now, the dates are evaluated as "2014-8-12" which as.Date() can see as proper dates. Also I've replaced seq() with seq.Date(), but I don't know if that is absolutely necessary. The code below worked for me:

scales_x <- facet_params %>% 
str_glue_data(
"`{zone}` = scale_x_date(limits = c(as.Date('{start_date}'), as.Date('{end_date}')), ",
"breaks = seq.Date(as.Date('{start_date}'), as.Date('{end_date}'), {breaks}))"
) %>%
str_flatten(", ") %>%
str_c("list(", ., ")") %>%
parse(text = .) %>%
eval()

library(facetscales)

ggplot(df, aes(date, Q)) +
geom_line() +
facet_grid_sc(~ zone, scales = list(x = scales_x))

Adjusting y axis limits in ggplot2 with facet and free scales

First, reproducibility with random data needs a seed. I started using set.seed(42), but that generated negative values which caused completely unrelated warnings. Being a little lazy, I changed the seed to set.seed(2021), finding all positives.

For #1, we can add limits=, where the help for ?scale_y_continuous says that

  limits: One of:

• 'NULL' to use the default scale range

• A numeric vector of length two providing limits of the
scale. Use 'NA' to refer to the existing minimum or
maximum

• A function that accepts the existing (automatic) limits
and returns new limits Note that setting limits on
positional scales will *remove* data outside of the
limits. If the purpose is to zoom, use the limit argument
in the coordinate system (see 'coord_cartesian()').

so we'll use c(0, NA).

For Q2, we'll add expand=, documented in the same place.

data %>%
gather(Gene, Levels, -Patient, -Treatment) %>%
mutate(Treatment = factor(Treatment, levels = c("Pre", "Post"))) %>%
mutate(Patient = as.factor(Patient)) %>%
ggplot(aes(x = Treatment, y = Levels, color = Patient, group = Patient)) +
geom_point() +
geom_line() +
facet_wrap(. ~ Gene, scales = "free") +
theme_bw() +
theme(panel.grid = element_blank()) +
scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.1)))

Sample Image

How to change the limits and divisions of the axes of each facet using ggplot2? Dealing with error in x$clone() attempt to apply non-function

I think I found the reason it doesn't work,

in facet_grid the scales parameter was used to indicate if each panel would have similar or different scales with c("free","free_x","free_y"). But having free_x on facet_grid is only free in the horizontal direction, and all vertical groupings have the same scale range.

When specifying facet_grid_sc, the scales parameter is used to distinguish how each scale will be rendered, specifically scales = list(x = scale_x) where scale_x matches cols = vars(Range)

library(ggplot2)
library(facetscales)

#Constructing data frame
Source <- c(rep("Water", 12), rep("Oil", 12))
Range <- rep((c(rep("First", 4), rep("Second", 8))),2)
Xaxis <- c(0,1,2,5,0,1,2,5,10,20,30,40,
0,1,2,5,0,1,2,5,10,20,30,40)
Yaxis <- c(0,1,2,5,0,1,2,5,10,20,30,40,
0,1,2,5,0,1,2,5,10,20,30,40)

DF <- data.frame(Source, Range, Xaxis, Yaxis)

p <- ggplot(data = DF, aes(x = Xaxis, y = Yaxis)) +
geom_smooth(method = "lm",
formula = y ~ x) +
geom_point()

#old plot without facet_grid_sc
p + facet_grid(rows = vars(Range),
cols = vars (Source))

Sample Image

You see how if you facet by Range on rows, they are split vertically instead of horizontality? I dont think facet_grid_sc supports a free_x while also specifiying the x element of scales

scale_x <- list(
First = scale_x_continuous(limits = c(0, 10), breaks = c(0, 2, 10)),
Second= scale_x_continuous(limits = c(0, 40), breaks = c(0, 5, 40))
)

#new plot where scale_x matches cols argument
p + facet_grid_sc(cols = vars(Range),
rows = vars (Source),
scales = list(x = scale_x))

Sample Image

Created on 2021-03-16 by the reprex package (v1.0.0)



EDIT

It should be noted that facet_grid_sc is probably more useful if you want to control the range or labels of each panel cols/rows individually. Using scales = "free_x" in facet_grid is actually pretty sufficient in this example.


p + facet_grid(cols = vars(Range),
rows = vars (Source),
scales = "free_x")

Sample Image

Created on 2021-03-16 by the reprex package (v1.0.0)

Change y axis limits for each row of a facet plot in ggplot2

I think your best option will be to trim the data before plotting it, e.g. with dplyr,

library(dplyr)
limits <- data.frame(variable = levels(dataM$variable),
min = c(1.9,0,0.3),
max = c(3,1,0.7))
dataC <- inner_join(dataM, limits) %>% filter(value > min, value < max)

last_plot() %+% dataC

Sample Image

(I initially made the points bigger to see the culprits more clearly)



Related Topics



Leave a reply



Submit