Home > Mobile >  Error in `combine_vars()`: ! At least one layer must contain all faceting variables: in function wit
Error in `combine_vars()`: ! At least one layer must contain all faceting variables: in function wit

Time:04-14

I am trying to create a function on Rthat creates and saves a dotplot with facets on my wd. Code for the function below:

get_dotplot <- function(df, xvalue, avgvalue, sdvalue, svalue, gvalue, main, xaxis, yaxis, glegend, figure_title)
{
  dp <- ggplot(df, aes(x = xvalue, y = avgvalue, color = gvalue))   
    
    geom_point(stat = 'identity', aes(shape=svalue, color=gvalue)) 
    
    geom_errorbar(aes(ymin=avgvalue-sdvalue, ymax=avgvalue sdvalue)) 
    
            facet_grid(cols = vars(svalue), scales = "fixed") 

        labs(x = xaxis, y = yaxis, title = main, color=glegend) 
 
        theme(axis.title.x.bottom = element_text(hjust = 0.5, vjust = 1),
              axis.title.y = element_text(hjust = 0.5, vjust = 1),
 
              axis.ticks.x = element_line(),
              axis.text.x = element_text(angle = 0, hjust = 1, vjust = 0.5, size = 7),
axis.ticks.x.bottom = element_line(colour = "grey", size = (0.5)),
axis.ticks.y.left = element_line(colour = "black", size = (0.4)),

panel.background=element_rect(colour = "black", size = 0.5, fill=NA),
panel.grid = element_blank())

    print(dp)
    ggsave(paste(figure_title, "png", sep = "."), plot = dp, scale = 1, dpi = 600)
}

get_dotplot(df, xvalue, avgvalue, sdvalue, svalue, gvalue, main, xaxis, yaxis, glegend, figure_title)

However, I always get this error message:

Error in `combine_vars()`:
! At least one layer must contain all faceting variables: `svalue`.
* Plot is missing `svalue`
* Layer 1 is missing `svalue`
* Layer 2 is missing `svalue`
Backtrace:
  1. global get_dotplot_errorbar_yaxis(...)
  3. ggplot2:::print.ggplot(dp)
  5. ggplot2:::ggplot_build.ggplot(x)
  6. layout$setup(data, plot$data, plot$plot_env)
  7. ggplot2 f(..., self = self)
  8. self$facet$compute_layout(data, self$facet_params)
  9. ggplot2 f(...)
 10. ggplot2::combine_vars(data, params$plot_env, cols, drop = params$drop)

I suspect it's because of the facetting so I played around between facet_wrap() and facet_grid() with no result. Could someone please help me with that ? I checked and I have the svalue variable in my dataframe, and it is spelled correctly. I also consulted previous questions about the topic but they were not helpful.

the dataset looks something like this, but with a larger number of individuals and numbers of days:

set.seed(108)
n <- 1:12
treatment <- factor(paste("trt", 1:2))
individuals <- sample(LETTERS, 2)
days <- c("12", "20", "25")
avg_var1 <- sample(1:100, 12) 
sd_var1 <- sample(1:50, 12) 
avg_var2 <- sample(1:100, 12) 
sd_var2 <- sample(1:50, 12) 
avg_var3 <- sample(1:100, 12) 
sd_var3 <- sample(1:50, 12)
test <- data.frame(n, treatment, individuals, days,avg_var1, sd_var1, avg_var2, sd_var2, avg_var3, sd_var3)

I define the variables for the function as follows on R:

df=test
xvalue=test$days
avgvalue=test$avg_var1
sdvalue = test$sd_var1
svalue=test$treatment
gvalue=test$individuals
main= "var1 in function of days"
xaxis="days"
yaxis="var1"
glegend="individuals"
figure_title ="var1_days"

CodePudding user response:

As written, your code passes columns into the function repeating the data in the dataframe. This doesn't seem to "play nicely" with the non-standard evaluation used in ggplot. Essentially ggplot is looking for a column in df called "svalue" to use for faceting (it doesn't find it). Once this has been fixed, the same sort of problem occurs with the error bars.

One way round this is to just pass in the column names, and use aes_string for the variables. This doesn't work for the faceting or the calculated values, so those are calculated at the start of the function. This would give:

get_dotplot <- function(df, xvalue, avgvalue, sdvalue, svalue, gvalue, main, xaxis, yaxis, glegend, figure_title)
{
  df$ymin <- df[[avgvalue]] - df[[sdvalue]]
  df$ymax <- df[[avgvalue]]   df[[sdvalue]]
  df$facets <- df[[svalue]]
  
  dp <- ggplot(df, aes_string(x = xvalue, y = avgvalue, color = gvalue))   
    
    geom_point(stat = 'identity', aes_string(shape=svalue, color=gvalue))  
    
    geom_errorbar(aes(ymin=ymin, ymax=ymax)) 
    
    facet_grid(cols = vars(facets), scales = "fixed") 
    
    labs(x = xaxis, y = yaxis, title = main, color=glegend) 
    
    theme(axis.title.x.bottom = element_text(hjust = 0.5, vjust = 1),
          axis.title.y = element_text(hjust = 0.5, vjust = 1),
          
          axis.ticks.x = element_line(),
          axis.text.x = element_text(angle = 0, hjust = 1, vjust = 0.5, size = 7),
          axis.ticks.x.bottom = element_line(colour = "grey", size = (0.5)),
          axis.ticks.y.left = element_line(colour = "black", size = (0.4)),
          
          panel.background=element_rect(colour = "black", size = 0.5, fill=NA),
          panel.grid = element_blank())
  
  print(dp)
  ggsave(paste(figure_title, "png", sep = "."), plot = dp, scale = 1, dpi = 600)
}

get_dotplot(df=test,
            xvalue="days",
            avgvalue="avg_var1",
            sdvalue = "sd_var1",
            svalue="treatment",
            gvalue="individuals",
            main= "var1 in function of days",
            xaxis="days",
            yaxis="var1",
            glegend="individuals",
            figure_title ="var1_days")
  • Related