Tianjian Qin
Tianjian Qin

Reputation: 630

Specifying formula for each facet using stat_poly_eq in ggplot2

I borrowed this example dataset from here:

# Load library
library(ggplot2)

# Load data
data(mtcars)

# Plot data
p <- ggplot(mtcars,aes(x = disp, y = mpg)) + geom_point() + facet_grid(gear ~ am)
p <- p + geom_smooth(method="lm")
print(p)

In above code the regression methods and formulae are the same in all facets. If we want to specify formula for facet (or panel) 6, we have the following code, from here:

# Smoothing function with different behaviour depending on the panel
custom.smooth <- function(formula, data,...){
  smooth.call <- match.call()

  if(as.numeric(unique(data$PANEL)) == 6) {
    # Linear regression
    smooth.call[[1]] <- quote(lm)
    # Specify formula
    smooth.call$formula <- as.formula("y ~ log(x)")
  }else{
    # Linear regression
    smooth.call[[1]] <- quote(lm)
  }

  # Perform fit
  eval.parent(smooth.call)
}

# Plot data with custom fitting function
p <- ggplot(mtcars,aes(x = disp, y = mpg)) + geom_point() + facet_grid(gear ~ am)
p <- p + geom_smooth(method = "custom.smooth", se = FALSE)
print(p)

Now if I want to add regression equations to these facets:

# Load library
library(ggpmisc)
p + stat_poly_eq(formula = y ~ x,aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~")), 
    parse=TRUE,label.x.npc = "right")

Then what should I do, to specify the equation and R2 displayed on panel 6, that can match the model I specified before? See the plot below, now panel 6 has its own fitting model, but the equation label doesn't. Maybe we can define a similar function as we did to ggplot2 parameters?

enter image description here

Upvotes: 6

Views: 9489

Answers (3)

Pedro J. Aphalo
Pedro J. Aphalo

Reputation: 6528

This answer does not exactly answer the question when considering details, but matches the title, so hopefully will be of some help to future visitors.

stat_poly_eq() is meant to be used with model formulas where the untransformed x (or the untransformed y) is the explanatory variable. It does not support a model formula like y ~ log(x) without manually replacing x by _log(x) in the equation label within the call, even if used in all panels. In the most recent version of 'ggpmisc' it is possible to have polynomials of different degrees in each panel using a user-defined method function.

library(ggpmisc)
#> Loading required package: ggpp
#> Loading required package: ggplot2
#> 
#> Attaching package: 'ggpp'
#> The following object is masked from 'package:ggplot2':
#> 
#>     annotate

poly_degree <- function(formula, data, ...) {
  if (all(data$PANEL == 6)) {
    formula <- y ~ poly(x, 2, raw = TRUE)
  }
  lm(formula = formula, data = data, ...)
}

ggplot(mtcars,aes(x = disp, y = mpg)) +
  geom_point() +
  stat_poly_line(method = "poly_degree") +
  stat_poly_eq(method = "poly_degree",
               use_label(c("eq", "r2")),
               size = 3,
               label.x = "right") +
  theme(legend.position = "bottom") + 
  facet_grid(gear ~ am)

Created on 2022-10-17 with reprex v2.0.2

Upvotes: 2

erocoar
erocoar

Reputation: 5893

You could update panel 6's formula individually (of course you could also update all panels with a function like that, but there's no need for that here)

rename_panel_expression <- function(grb, panel, expr) {
  g <- grb$grobs[[panel + 1]]$children
  grb$grobs[[panel + 1]]$children[[grep("GRID.text", names(g))]]$label <- expr
  grb
}

l <- lm(mpg ~ log(disp), mtcars[mtcars$am == 1 & mtcars$gear == 5, ])

tt <- rename_panel_expression(ggplotGrob(p), 6, 
  bquote(italic(y)~`=`~.(round(l$coefficients[1], 3)) - .(round(abs(l$coefficients[2]), 3))*~italic(x)~~~italic(R)^2~`=`~.(round(summary(l)$r.squared, 3))))

grid::grid.newpage()
grid::grid.draw(tt)

enter image description here

Upvotes: 2

nadizan
nadizan

Reputation: 1373

It seems like the function you are calling custom.smooth contains a row that defines the formula as "y ~ log(x)". Therefore, you need to also specify this in your stat_poly_eq function, hence the polynomial shape (but in reality logarithmic) of a linear looking equation.

I.e. add:

p + stat_poly_eq(formula = y ~ log(x),
                     aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~")), 
                     parse=TRUE,label.x.npc = "right")

Upvotes: 3

Related Questions