How to show a dynamic number of ggplot2 objects ...

Everything related to the development of modules in jamovi
Post Reply
jojop2
Posts: 4
Joined: Thu Jan 23, 2025 2:21 pm

How to show a dynamic number of ggplot2 objects ...

Post by jojop2 »

I have a grouping variable.
For each single value a list of plots is given back, which I need to show in the result pane.

With a specific title and description for each plot.

How is that working?
User avatar
jonathon
Posts: 2837
Joined: Fri Jan 27, 2017 10:04 am

Re: How to show a dynamic number of ggplot2 objects ...

Post by jonathon »

do you know the number of plots there will be "in advance" or is it hard to predict and depends on what the analysis finds?

jonathon
jojop2
Posts: 4
Joined: Thu Jan 23, 2025 2:21 pm

Re: How to show a dynamic number of ggplot2 objects ...

Post by jojop2 »

I can calculate the number of plots in advance, based on the unique values in the group column of the dataset.

I forgot to mention, that my existing function returns the plots in a list. So the plots cannot be build up from scratch in jamovi.

Thank you!
Joe
User avatar
jonathon
Posts: 2837
Joined: Fri Jan 27, 2017 10:04 am

Re: How to show a dynamic number of ggplot2 objects ...

Post by jonathon »

i think you want something like this in your .r.yaml :

Code: Select all

    - name: plots
      title: Plots
      type: Array
      description: an array of plots
      items: (levels(vars))    #  substitute in the name of your Variable option into "vars"
      template:
          title: $key
          type: Image
          description: descriptives plot
          width: 350
          height: 300
          renderFun: .plot
jonathon
jojop2
Posts: 4
Joined: Thu Jan 23, 2025 2:21 pm

Re: How to show a dynamic number of ggplot2 objects ...

Post by jojop2 »

Thank you for the immediate reply.

Is it possible to define, that if the vars is not filled, only one plot is built and otherwise the "levels(vars)"?

Is it correct, that I don't need the .run function, only the .plot function, if I only want to show plots?

How I understand it now, I would write sth like this in the .plot function:
list_of_plots <- externalFunctionCreatingPlots(self$data, self$options$measure, self$options$groups)

Do I have to iterate over the plot list to print each?

Joe
User avatar
jonathon
Posts: 2837
Joined: Fri Jan 27, 2017 10:04 am

Re: How to show a dynamic number of ggplot2 objects ...

Post by jonathon »

> Is it possible to define, that if the vars is not filled, only one plot is built and otherwise the "levels(vars)"?

if you're wanting that, then you'll need to pursue a different approach ... leave the items property undefined, define a method called .init() alongside .run() ... and call

self$results$nameOfPlotArrayObject$addItem(key=nameOfPlot)

as many times as you'd like plots.

> Is it correct, that I don't need the .run function, only the .plot function, if I only want to show plots?

we generally try and minimise what runs inside a plot function, and try to do most of the processing inside of the .run function. ideally, the run function calculates the minimal geometry for a plot, than minimal geometry gets stored in the plots state, and then the plot function does the absolute minimum mapping the geometry to the plot device.

if the user wants to export the plot, no problem, we load the state, and create the plot in the target format ... without having to do any additional computation.

of course, in practice, many R packages make this difficult if not impossible ... and so such a neat separation between "computation" and "presentation" isn't always possible. we sometimes end up performing the *whole* analysis again, just because the user requested to export a different format.

> list_of_plots <- externalFunctionCreatingPlots(self$data, self$options$measure, self$options$groups)

if you're using self$data inside your plotting code, then you'll need to add

requiresData: true

to the plot object in the .r.yaml ...

and then you'll want something like

.plot = function(image, ...) {
list_of_plots <- externalFunctionCreatingPlots(self$data, self$options$measure, self$options$groups)
plot <- list_of_plots[[image$key]]
return(plot)
}

this is inefficient of course, as if you have 5 plots, externalFunction will be called 5 times.

jonathon
Post Reply