Search code examples
rggplot2axisfacetfacet-wrap

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 am creating a graph divided into facets. Some of these facets need to be on a smaller scale for better viewing. I have already applied several tricks to achieve this. However, I need to change the limits and divisions of the axes of some facets.

Calling the necessary packages, creating the database and making the plot

devtools::install_github("zeehio/facetscales")
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)
      
#plot
p <- ggplot(data = DF, aes(x = Xaxis, y = Yaxis)) +
  geom_smooth(method = "lm",
              formula = y ~ x) +
  geom_point()

I initially used facet_wrap with scales = "free", but what I really want is to be able to modify the limits and divisions of the x-axis of the facets in the "First" row.

#plot using facet wrap
p + facet_wrap(Range~Source,
               scales = "free") +
  ggtitle("Using facet_wrap")

enter image description here

So I chose to use the facetscales package and followed this (1) and this (2) examples

#axis specifications
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))
)

#plot using facet grid and the facetscales package
p + facet_grid_sc(rows = vars(Range),
                  cols = vars (Source),
                  scales = list(x = scale_x)) +
  ggtitle("Using facet_grid_sc")

When trying to make the graph with the specifications that I need appears:

error in x$clone() attempt to apply non-function

I don't understand what I'm doing wrong. Could someone help me, please?


Solution

  • 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))
    

    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))
    

    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")
    

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