Why does my function not create dataframes?

I'm trying to build my first package, but the code that worked perfectly as just code doesn't work as a function. I want to have a function which also puts two empty dataframes into the environment. I need them to be empty since I'm using a loop which stores all it's information into those dataframes with rbind with every iteration.
While the rest of the function runs through without an error message, it doesn't create any dataframes. Why does my function not return any objects?

I created a simplified example, I hope that's enough to demonstrate my problem.

a <- function(x){
  object <- x
  emptydf <- data.frame()
  anotherdf <- data.frame()
}

A function returns its last argument. So the function is returning anotherdf.

2 Likes

As @startz said, by default R only returns the last evaluated expression in a function.
You can use r's return() method to get around this.

Here is some more information on the return method: R Return Value from Function - DataMentor

2 Likes

Not a direct answer but you might also be able to use a different way to create the final data.frames, e.g. with purrr or another way to iterate (e.g. lapply and then do.call+rbind)? Having a function create empty data.frames is not conventional (I'm not saying it's necessarily bad, though).

Pseudo-code.

calculate_thing <- function(stuff) {
 # this returns a df
  blabla(stuff)
}
calculate_thing2 <- function(stuff) {
 # this returns a df
  blabla2(stuff)
}
# stuff_list is assumed to be a list
df <- purrr::map_df(stuff_list, calculate_thing)
df2 <- purrr::map_df(stuff_list, calculate_thing2)

purrr intro.

If your input data is in a data.frame you might also enjoy dplyr rowwise operations.

This slidedeck by Jenny Bryan might have slightly outdated tidyverse advice given recent changes (e.g. the rowwise vignette linked above is more recent) but this quote is still very valid:

"Of course someone has to write loops. It doesn’t have to be you."

1 Like

Below I provide an example that shows how to do what you ask. At the same time I don't feel great about it because coding in this way can be rife with programming pitfalls for you and the users of your package to fall into. best of luck.

a <- function(x){
  object <- x
  empty_df <- data.frame()
  another_df <- data.frame()
  assign("empty_df",value = empty_df,envir = .GlobalEnv)
  assign("another_df",value = another_df,envir = .GlobalEnv)
  
return(NULL)
}
2 Likes

Thank you all for your help! I will look into purr and try to use lists, since that seems to be the most common and most effective way.

1 Like