1

Trying to pass into a function what I want it to name the dataframe it creates, then save it to global environment.

I am trying to automate creating dataframes that are subsets of other dataframes by filtering for a value; since I'm creating 43 of these, I'm writing a function that can automatically:

  • a) subset rows containing a certain string into it's own data.frame then
  • b) name a dataframe after that string and save it to my global environment. (The string in a) is also the suffix I want it to name the data.frame after in b))

I can do a) fine but am having trouble with b).

Say I have a dataset which includes a column named "Team" (detailing whose team that member belongs to):

original.df <- read_csv("../original_data_set")

I create a function to split that dataset according to values in one of its columns...

split.function <- function(string){
    x <- original.df
    as.name(string) <<- filter(x, str_detect(`Team`, string))
}

... then save the dataframe with the name:

split.by.candidate('Team.Curt')

I keep getting:

> Error in as.name(x) <<- filter(y, str_detect(`Receiving Committee`, x)) : 
  object 'x' not found

But I just want to see Team.Curt saved as a data.frame in my global environment when I do this with rows including the term Team.Curt

smci
  • 32,567
  • 20
  • 113
  • 146
  • I tried to rewrite the question to be less repetitive and verbose. Essentially you want to parameterize the string name of a dataframe to be used in an `assign` statement, that's all. (The fact that you also want to use that same string in the filter operation is irrelevant.) But your only issue is that you omitted `assign(..., envir = .GlobalEnv)`. And `as.name(string) <<- ...` is not how you do an assign. That's all. – smci Mar 27 '19 at 07:38
  • Related: [Vectorize the assign function and create objects in global environment](https://stackoverflow.com/questions/50646629/vectorize-the-assign-function-and-create-objects-in-global-environment) – smci Mar 27 '19 at 07:38
  • The answer to the question you didn't ask is if you're doing a lot of this, tidyverse is probably a better approach. – smci Mar 27 '19 at 07:55

2 Answers2

1

You can use assign to create objects based on a string:

split.function <- function(string){
   x <- original.df
   assign(string, filter(x, str_detect(`Team`, string)), envir = .GlobalEnv)
}

Here, envir = .GlobalEnv is used to assign the value to the global environment.

Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
0

Both <- and <<- assignments require that the statement hardcodes the object name. Since you want to parameterize the name, as in your cases, you must use assign().

<<- is merely a variant of <- that can be used inside a function, and does a bottom-up search of environments until it either reaches the top (.GlobalEnv) or finds an existing object of that name. In your case that's unnecessary and slightly dangerous, since if an object of that name existed in some environment halfway up the hierarchy, you'd pick it up and assign to it instead.

So just use assign(..., envir = .GlobalEnv) instead.

But both <<- or assigning directly into .GlobalEnv within functions are strongly discouraged as being disasters in waiting, or "life by a volcano" (burns-stat.com/pages/Tutor/R_inferno.pdf). See the caveats at Assign multiple objects to .GlobalEnv from within a function. tidyverse is probably a better approach for managing multiple dataframes.

smci
  • 32,567
  • 20
  • 113
  • 146