0

I want to write a function that returns both a dataframe and a ggplot. Simply printing the ggplot in the function is not enough, as it will need to be used later in ggarrange(). I need to store both the ggplot and the dataframe in variables to be used later in a pipeline.

For example, if I want to return a box plot and the top 20% highest-distance cars:

library('ggplot2')

plotCars <- function(d){
  
  dm <- suppressMessages(melt(d))
  
  p <- ggplot(dm, aes(x=variable, y=value, fill=variable)) +
    geom_boxplot(width=0.2)
  
  q <- quantile(d$dist, prob=c(0.8))
  dq <- d[d$dist > q[1],]
  
  return(c(list(p), dq))
}

obj <- plotCars(cars)

Calling obj[[1]] prints the plot as expected. enter image description here

But the dataframe gets stored as invidual columns in the output object. E.g. obj[2] gives the $speed column, and obj[3] gives the $dist column.

This ruins the structure of the dataframe and undermines the next steps of the pipeline that use it. How do I fix this?

jpsmith
  • 11,023
  • 5
  • 15
  • 36
  • 7
    You need `return(list(p, dp))` – Onyambu Jun 28 '23 at 18:17
  • 2
    This existing question covers this topic and the solution in a more clear and concise manner: [Returning multiple objects in an R function](https://stackoverflow.com/questions/8936099/returning-multiple-objects-in-an-r-function) – Matt Summersgill Jun 28 '23 at 18:48

1 Answers1

3

Here is a function that follows what has been written in two comments, Onyambu's and MrFlick's. The only difference is that it returns a named list, in order to make things more clear (I hope).
It also somewhat simplifies the function's code.

library('ggplot2')

plotCars <- function(d){
  dm <- suppressMessages(reshape2::melt(d))
  
  p <- ggplot(dm, aes(x=variable, y=value, fill=variable)) +
    geom_boxplot(width=0.2)
  
  i <- d$dist > quantile(d$dist, prob = 0.8)
  dq <- d[i, ]
  
  list(plot = p, data = dq)
}

obj <- plotCars(cars)

obj$plot  # the plot accessed as a named list member
obj[[1]]  # same list member

obj$data  # the data accessed as a named list member
obj[[2]]  # same list member
Rui Barradas
  • 70,273
  • 8
  • 34
  • 66