Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Center Axes in ggplot2

Tags:

r

ggplot2

In the following plot, which is a simple scatter plot + theme_apa(), I would like that both axes go through 0. enter image description here

I tried some of the solutions proposed in the answers to similar questions to that but none of them worked.

A MWE to reproduce the plot:

library(papaja)
library(ggplot2)
library(MASS)

plot_two_factor <- function(factor_sol, groups) {
  the_df <- as.data.frame(factor_sol)
  the_df$groups <- groups
  p1 <- ggplot(data = the_df, aes(x = MR1, y = MR2, color = groups)) +
    geom_point() + theme_apa()

}

set.seed(131340)
n <- 30
group1 <- mvrnorm(n, mu=c(0,0.6), Sigma = diag(c(0.01,0.01)))
group2 <- mvrnorm(n, mu=c(0.6,0), Sigma = diag(c(0.01,0.01)))
factor_sol <- rbind(group1, group2)
colnames(factor_sol) <- c("MR1", "MR2")
groups <- as.factor(rep(c(1,2), each = n))

print(plot_two_factor(factor_sol, groups))

The papaja package can be installed via

devtools::install_github("crsh/papaja")
like image 647
Julian Karch Avatar asked Feb 03 '26 21:02

Julian Karch


2 Answers

What you request cannot be achieved in ggplot2 and for a good reason, if you include axis and tick labels within the plotting area they will sooner or later overlap with points or lines representing data. I used @phiggins and @Job Nmadu answers as a starting point. I changed the order of the geoms to make sure the "data" are plotted on top of the axes. I changed the theme to theme_minimal() so that axes are not drawn outside the plotting area. I modified the offsets used for the data to better demonstrate how the code works.

library(ggplot2)

iris %>% 
  ggplot(aes(Sepal.Length - 5, Sepal.Width - 2, col = Species)) +
  geom_hline(yintercept = 0) +
  geom_vline(xintercept = 0) +
  geom_point() +
  theme_minimal()

This gets as close as possible to answering the question using ggplot2.

enter image description here

Using package 'ggpmisc' we can slightly simplify the code.

library(ggpmisc)

iris %>% 
  ggplot(aes(Sepal.Length - 5, Sepal.Width - 2, col = Species)) +
  geom_quadrant_lines(linetype = "solid") +
  geom_point() +
  theme_minimal()

This code produces exactly the same plot as shown above.

If you want to always have the origin centered, i.e., symmetrical plus and minus limits in the plots irrespective of the data range, then package 'ggpmisc' provides a simple solution with function symmetric_limits(). This is how quadrant plots for gene expression and similar bidirectional responses are usually drawn.

iris %>% 
  ggplot(aes(Sepal.Length - 5, Sepal.Width - 2, col = Species)) +
  geom_quadrant_lines(linetype = "solid") +
  geom_point() +
  scale_x_continuous(limits = symmetric_limits) +
  scale_y_continuous(limits = symmetric_limits) +
  theme_minimal()

enter image description here

The grid can be removed from the plotting area by adding + theme(panel.grid = element_blank()) after theme_minimal() to any of the three examples.

Loading 'ggpmisc' just for function symmetric_limits() is overkill, so here I show its definition, which is extremely simple:

symmetric_limits <- function (x) 
{
    max <- max(abs(x))
    c(-max, max)
}
like image 57
Pedro J. Aphalo Avatar answered Feb 05 '26 11:02

Pedro J. Aphalo


For the record, the following also works as above.

iris %>%
    ggplot(aes(Sepal.Length-6.2, Sepal.Width-3.2, col = Species)) +
    geom_point() +
    geom_hline(yintercept = 0) +
    geom_vline(xintercept = 0)
like image 25
Job Nmadu Avatar answered Feb 05 '26 11:02

Job Nmadu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!