Set Upper Limit in Ggplot to Include Label Greater Than the Maximum Value

set upper limit in ggplot to include label greater than the maximum value

What about the following solution:

library(ggplot2)

d <- data.frame(x=1:11, y=c(11:17,5:2))
px <- pretty(d$x)
py <- pretty(d$y)

ggplot(d, aes(x,y)) + geom_point() +
scale_x_continuous(breaks=px, limits=range(px)) +
scale_y_continuous(breaks=py, limits=range(px))

Sample Image

How to expand ggplot y axis limits to include maximum value

You can use expand_limits() to increase the maximum y-axis value. You can also ensure that the maximum y-axis value is rounded up to the next highest value on the scale of the data, e.g., next highest tens value, next highest hundreds value, etc., depending on the whether the highest value in the data is within the tens, hundreds, etc.

For example, the function below finds the base 10 log of the maximum y value and rounds it down. This gives us the base ten scale of the maximum y value (e.g., tens, hundreds, thousands, etc.). It then rounds the maximum y-axis value up to the nearest ten, hundred, etc., that is higher than the maximum y value.

expandy = function(vec, ymin=NULL) {

max.val = max(vec, na.rm=TRUE)
min.log = floor(log10(max.val))

expand_limits(y=c(ymin, ceiling(max.val/10^min.log)*10^min.log))
}

p = mtcars %>% ggplot(aes(x=mpg, y = hp)) +
geom_point()

p + expandy(mtcars$hp)

p + expandy(mtcars$hp, 0)

Or, to make things a bit easier, you could set up the function so that the y-range data is collected directly from the plot:

library(gridExtra)

expandy = function(plot, ymin=0) {

max.y = max(layer_data(plot)$y, na.rm=TRUE)
min.log = floor(log10(max.y))

expand_limits(y=c(ymin, ceiling(max.y/10^min.log)*10^min.log))
}

p = mtcars %>% ggplot(aes(x=mpg, y = hp)) +
geom_point()

grid.arrange(p, p + expandy(p), ncol=2)

Sample Image

p = iris %>% ggplot(aes(x=Sepal.Width, y=Petal.Width)) +
geom_point()

grid.arrange(p, p + expandy(p), ncol=2)

Sample Image

Dynamically use range of pretty breaks to set limits in ggplot

I had this problem crop up again a long time later and found a more rigorous (although not beautiful) approach. Posting in case other people find it helpful.

This requires a custom limits and custom breaks function. The custom breaks function is required because when you call breaks=pretty_breaks() this is passed the limits of the plot, but these limits are both, already adjusted by the limits=... and then also expanded (in line with expand = ... by default multipled by 0.05). So to make sure the pretty breaks line up with the limits based on the original pretty breaks you need to try and back-derive particularly the expansion. This isn't going to be 100% perfect and assumes the default expansion.

I have also included a threshold so the limits don't go below 0 which is useful for me as the numbers I am dealing with a strictly positive but might be close to 0 so a small expansion pushes it below 0. But may not be as useful to others

library(ggplot2)
library(scales)
set.seed(1)
rdat <- data.frame(x = 1:1000,y=runif(1000,min = 0, max = 107))

pretty_lim <- function(x,n=5){
#pretty_lim
r2 <- ifelse(x <0, 0, x)
pr <- pretty(r2,n)
r_out <- range(pr)
r_out
}

pretty_unexpanded <- function(x,n=5){
#expand_limit
if(x[1]<=0){
r2 <- x + c(-x[1],x[1])
}else{
r2 <- x + c((x[2]-x[1])*0.04545455,-(x[2]-x[1])*0.04545455)
}
pout <- pretty(r2,n)
pout
}

#expand near 0
ggplot(rdat, aes(x =x, y = y))+geom_point()+
scale_y_continuous( breaks=pretty_unexpanded,limits = pretty_lim )

Sample Image

#another case no where near 0
rdat2 <- rdat
rdat2$y <- rdat2$y +45

ggplot(rdat2, aes(x =x, y = y))+geom_point()

#Raw Plot

Sample Image

ggplot(rdat2, aes(x =x, y = y))+geom_point()+
scale_y_continuous( breaks=pretty_unexpanded,limits = pretty_lim )

#updated plot with new limits and breaks

Sample Image

Created on 2021-06-07 by the reprex package (v0.3.0)

How to set just one limit for axes in ggplot2 with facets?

Set limits one-sided with NA. Works both in coord_ and scale_ functions

I generally prefer coord_ because it does not remove data. For the example below you would additionally need to remove the margin at 0, e.g. with expand.

library(ggplot2)    

carrots <- data.frame(length = rnorm(500000, 10000, 10000))
cukes <- data.frame(length = rnorm(50000, 10000, 20000))
carrots$veg <- 'carrot'
cukes$veg <- 'cuke'
vegLengths <- rbind(carrots, cukes)

ggplot(vegLengths, aes(length, fill = veg)) +
geom_density(alpha = 0.2) +
scale_x_continuous(limits = c(0, NA))
#> Warning: Removed 94542 rows containing non-finite values (stat_density).

Sample Image


ggplot(vegLengths, aes(length, fill = veg)) +
geom_density(alpha = 0.2) +
coord_cartesian(xlim = c(0, NA))

Sample Image

Created on 2020-04-30 by the reprex package (v0.3.0)

remove the margin with expand. Also one sided possible. the right margin is set to the default mult expansion of 0.05 for continous axis.

ggplot(vegLengths, aes(length, fill = veg)) +
geom_density(alpha = 0.2) +
scale_x_continuous(expand = expansion(mult = c(0, 0.05))) +
coord_cartesian(xlim = c(0, NA))

Sample Image

Label minimum and maximum of scale fill gradient legend with text: ggplot2

For scale_fill_gradientn() you should provide both arguments: breaks= and labels= with the same length. With argument limits= you extend colorbar to minimum and maximum value you need.

ggplot(df, aes(x, y, fill = z)) + geom_raster() + 
scale_fill_gradientn(colours=topo.colors(7),na.value = "transparent",
breaks=c(0,0.5,1),labels=c("Minimum",0.5,"Maximum"),
limits=c(0,1))

Sample Image

How to set limits for axes in ggplot2 R plots?

Basically you have two options

scale_x_continuous(limits = c(-5000, 5000))

or

coord_cartesian(xlim = c(-5000, 5000)) 

Where the first removes all data points outside the given range and the second only adjusts the visible area. In most cases you would not see the difference, but if you fit anything to the data it would probably change the fitted values.

You can also use the shorthand function xlim (or ylim), which like the first option removes data points outside of the given range:

+ xlim(-5000, 5000)

For more information check the description of coord_cartesian.

The RStudio cheatsheet for ggplot2 makes this quite clear visually. Here is a small section of that cheatsheet:

Sample Image

Distributed under CC BY.

Is there a programatic way to pass specific ranges for the y-axis on a ggplot2 plot?

Inspired by teunbrand, I built a function that generates the limits, then checks to ensure that the expansion (including the 5% buffer) does not change the output of pretty

my_lims_expand <- function(x){
prev_pass <-
range(pretty(x))

curr_pass <-
pretty(c(prev_pass[1] - 0.05 * diff(prev_pass)
, prev_pass[2] + 0.05 * diff(prev_pass)))

last_under <-
tail(which(curr_pass < min(x)), 1)

first_over <-
head(which(curr_pass > max(x)), 1)

out <-
range(curr_pass[last_under:first_over])

confirm_out <-
range(pretty(out))

while(!all(out == confirm_out)){
prev_pass <- curr_pass

curr_pass <-
pretty(c(prev_pass[1] - 0.05 * diff(prev_pass)
, prev_pass[2] + 0.05 * diff(prev_pass)))

last_under <-
tail(which(curr_pass < min(x)), 1)

first_over <-
head(which(curr_pass > max(x)), 1)

out <-
range(curr_pass[last_under:first_over])

confirm_out <-
range(pretty(out))
}


return(out)
}

Then, I can use that function for limits:

ggplot(sample_data, 
aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
scale_y_continuous(
limits = my_lims_expand
, breaks = pretty
)

to generate the desired plot:

Sample Image

Can I limit ggplot axis range EXACTLY?

As Axeman noted, specifying limits in scale_y_continuous() would limit the y-axis. Another alternative is to add coord_cartesian(ylim = c(20, 73)) to your code.

The difference between the two (irrelevant for geom_point) is that scale_y_continuous(limits = c(...)) would restrict the range of values passed to ggplot for plotting, while coord_cartesian(ylim = c(...)) retricts the visible range after everything has been plotted.

The ggplot2 package cheatsheet over at RStudio summarises this nicely:

illustration

As for your issue with some points being cut off at the edge of the panel, you can get around it by converting the plot to a grob, & turning off the panel's clipping:

# plot with restricted range
p <- ggplot(data = mydata, aes(x = x, y = y)) +
geom_point(shape = 21, size = 5, color = "black", fill = "orange", stroke = 1) +
scale_x_continuous(name = 'Number of Contacts') +
scale_y_continuous(name = "Remembered (%)",
expand = c(0, 0),
sec.axis = sec_axis(trans = ~ (.-min(.))*100/(max(.)-min(.)),
name = "Remembered (Index)",
breaks = break2)) +
coord_cartesian(ylim = c(20, 73)) +
theme(plot.margin = margin(t = 10, unit = "pt")) # increase top margin as some points
# are very close to the top edge

# convert to grob
gp <- ggplotGrob(p)

grid::grid.draw(gp) # verify that the points at the edge are cut off

# turn off clipping for panel
gp$layout$clip[gp$layout$name=="panel"] <- "off"

grid::grid.draw(gp) # points at the edge are now visible

plot



Related Topics



Leave a reply



Submit