Bug in the Gamlj Plot method when using R

General help and assistance with jamovi. Bug reports can be made at our issues page: https://github.com/jamovi/jamovi/issues . (If you're unsure feel free to discuss it here)
Post Reply
Whirly123
Posts: 36
Joined: Mon May 06, 2019 3:07 pm

Bug in the Gamlj Plot method when using R

Post by Whirly123 »

I tend to use Gamlj in R and I usually extract the plot object like this:

plotObject <- plot(model)

However, this doesn't always work across the different models. For example it works in Gamlj 3 mixed models but not Gamlj 2 mixed models. It seems a bit inconsistent throughout, so I sometimes have to swap over.

The error I get is:
'descPlots' does not exist in this results element

I would hazard a guess that things aren't being named correctly as the plot object inside the model is actually called "mainPlots" not "descPlots" so the plot method won't work.

I hoped a work around would be to rename the object or copy it into something with the right name something like:
model$descPlots <- model$mainPlots

but that doesn't work as I get the error:
model$descPlots <- NA :
cannot add bindings to a locked environment

This now goes beyond my R knowledge. Help appreciated as I tend to rely on Galmj in R for almost everything and always need to edit the plots using ggplot.
Whirly123
Posts: 36
Joined: Mon May 06, 2019 3:07 pm

Re: Bug in the Gamlj Plot method when using R

Post by Whirly123 »

I guess in addition how would I go about viewing the Gamlj code myself to see how ggplots were generated so I could potentially recreate some of it myself outside of gamlj with just an lmer or lm object? I tried ctrl clicking the gamljlm text but that doesn't quite send me to right place.
User avatar
mcfanda@gmail.com
Posts: 492
Joined: Thu Mar 23, 2017 9:24 pm

Re: Bug in the Gamlj Plot method when using R

Post by mcfanda@gmail.com »

Hi
it seems that the issue is due to the two versions being loaded at the same time. When you get the error "Error: 'descPlots' does not exist in this results element" is because `plot()` from gamlj 2 is applied to a GAMLj3 object. So, be sure that you load only the version you want to use.

Aside from the function plot() you can get the plot in gamlj version 2 as follows:

Code: Select all

mod1<-gamlj::gamljMixed(
  formula = ycont~ 1 + x+( 1 | cluster ),
  data = clustermanymodels,
  plotHAxis = x)

myplot<-mod1$descPlot
and in GAMLj3

Code: Select all

mod1<-GAMLj3::gamlj_mixed(
  formula = ycont~ 1 + x+( 1 | cluster ),
  data = clustermanymodels,
  plot_x = x,
  ci_method = "wald")

myplot<-mod1$mainPlots

Please notice that version 2 is no longer maintained, so no update or bug fix will be done for it. GAMLj3 is the version that is constantly checked and updated
Whirly123
Posts: 36
Joined: Mon May 06, 2019 3:07 pm

Re: Bug in the Gamlj Plot method when using R

Post by Whirly123 »

Thanks for the help - there does still seem to be an issue with doing it this way:

myplot<-mod1$mainPlots

I can print the myplot object and it will print the plot but the object itself isn't a ggplot object in the the way using myplot <- plot(mod1) is.

So for example if I do something like :
myplot + theme_bw() it just returns NULL

Using the plot method returns a list (ggplot object) whereas mod1$mainPlots is an "object with active binding".

If I try to do this: plot(mod1$mainPlots) I get the error
Error: 'plot' does not exist in this results element

So none of that is really "extracting" the actually ggplot object for me.
User avatar
mcfanda@gmail.com
Posts: 492
Joined: Thu Mar 23, 2017 9:24 pm

Re: Bug in the Gamlj Plot method when using R

Post by mcfanda@gmail.com »

mod1$mainPlots contains an array of ggplot2 objects. This is because a model may need to produce more than one plot (think of a four-way interaction plot). Thus, to get the ggplot object you need to run

myplot<-mod1$mainPlots[[1]].

What plot() function does is to inspect $mainPlots, if it finds only one plot it returned as a ggplot2 object, if there are more than one plot it returns a list of ggplot2 objects. Thus, using plot() is recommended because it simplifies the returned object, but both methods work.
Whirly123
Posts: 36
Joined: Mon May 06, 2019 3:07 pm

Re: Bug in the Gamlj Plot method when using R

Post by Whirly123 »

Sorry I should have said in the previous post that I tried that too. The model only had one plot and yet I still extracted myplot<-mod1$mainPlots[[1]] because I figured it might be in an array.

Sadly, this still doesn't extract a ggplot object - it still prints a plot but still returns Null if I try to edit it as a ggplot (e.g. "myplot + theme_bw()" or whatever).


To make this easier to deal with I have made a reproducable example for you:

Code: Select all

library("tidyverse")
library("jmv")
library("GAMLj3")

data("selfesteem", package = "datarium")

longData <- pivot_longer(data = selfesteem,
             cols = t1:t3,
             names_to = "time")

longData$time <- as.factor(longData$time)

model <- GAMLj3::gamljlm(
  formula = value ~ 1 + 
    time +
    ( 1 | id ),
  data = longData,
  plot_x = time,
  plot_around='ci')

# this returns my lovely editable ggplot
methodPlot <- plot(model)

# and this works fine :)
methodPlot + theme_bw()

# this returns an "object containing active binding rather than a ggplot
extractedPlot <- model$mainPlots

# And so this returns NULL
extractedPlot + theme_bw()

# this also returns an "object containing active binding rather than a ggplot
extractedPlot <- model$mainPlots[[1]]

# And so this also returns NULL
extractedPlot + theme_bw()

I realise you have technically solved my problem since the plot method obviously now works fine but I would love to know what is happening here as it would increase my R knowledge (thanks in advance ':) !). And I love gamlj so being able wrangle more stuff out of it is useful. There is a ggplot object somewhere I should be able to extract it right (without the plot method)?
User avatar
mcfanda@gmail.com
Posts: 492
Joined: Thu Mar 23, 2017 9:24 pm

Re: Bug in the Gamlj Plot method when using R

Post by mcfanda@gmail.com »

sure. To dig into the gamlj object (as for any other complex object in R) my suggestion when exploring these functionalities is to use `class()` and `str()`, so we know what object are returned.
First, the recommended method

Code: Select all

 methodPlot<-plot(model)
 class(methodPlot)
[1] "gg"     "ggplot"
so methodPlot is a ggplot object that can be manipulated with ggplot code.

accessing the plot from the gamlj object returns an array of jamovi Images, each Image has a function $plot$fun() that returns the ggplot object

Code: Select all

> class(extractPlot)
[1] "Array"          "ResultsElement" "R6"            

class(extractPlot[[1]])
[1] "Image"          "ResultsElement" "R6"            
one<-extractPlot[[1]]
class(one$plot$fun())
[1] "gg"     "ggplot"
> 

To be sure, here is a snippet from the plot() function that may interest you (other code in the function is not relevant here)

Code: Select all

   plots <- list()
        for (i in 1:length(object$mainPlots)) {
            title <- object$mainPlots[[i]]$title
            gplot <- object$mainPlots[[i]]$plot$fun() + ggplot2::ggtitle(title)
            plots[[i]] <- gplot
       }
    if ("list" %in% class(plots) && length(plots) == 1) 
        plots <- plots[[1]]
    plots
[code]
Whirly123
Posts: 36
Joined: Mon May 06, 2019 3:07 pm

Re: Bug in the Gamlj Plot method when using R

Post by Whirly123 »

Amazing!

Thanks so much that was super useful!
Post Reply