2

I am attempting to write a function that combines data based on a user input.

I've searched around but cannot find anything that seems to help (I am somewhat new to using R).

Running each line separately works great. However, when I wrap them into a used defined function nothing is produced. For example, I have the following data: ASW1_2016, ASW_2017, ASW_2018, CSW_2015, CSW_2017. I want to prompt the user to input a site name "ASW1" and have the function combine all data that contain this name.

#Running these two lines separately works:
Site <- invisible(readline(prompt = "Enter Site Name:"))

assign(Site, rbindlist(mget(apropos(Site), inherits = TRUE))

#Putting these two lines into a function does not produce anything:
CombineData <- function()

{

Site <- invisible(readline(prompt = "Enter Site Name:"))

assign(Site, rbindlist(mget(apropos(Site), inherits = TRUE))

}

CombineData()

After being asked to enter a site name (e.g. ASW1) I expect all data containing this name to be combined and assigned the name provided by the user. However, as stated above, when I run CombineData() and enter the site name following the prompt, nothing happens.

josliber
  • 43,891
  • 12
  • 98
  • 133
bmdanhof
  • 23
  • 2

1 Answers1

1

assign called within a function by default does the assignment in the function's environment, instead of in the global environment. So basically, it's like storing the result in a variable within the function. Once the function returns, that value is lost. The following illustrates this (this is essentially what you are doing):

fxn <- function() assign("xyz", 1)
fxn()
print(xyz)
# Error in print(xyz) : object 'xyz' not found

If you want to use assign to store in the global environment (outside of the function), you could add argument envir = .GlobalEnv to your call to assign.

fxn <- function() assign("xyz", 1, envir = .GlobalEnv)
fxn()
print(xyz)
# [1] 1

That being said, using assign to store values is often not the preferred way to store data in R (you can read more about that at Why is using assign bad?). You might find it easier to maintain your code if you stored it in a list. As an example, if you had an initial list l <- list(), then you could store your new data in that list with l[[Site]] <- rbindlist(mget(apropos(Site), inherits = TRUE) and access it with [[ or $.

josliber
  • 43,891
  • 12
  • 98
  • 133
  • Thank you for the solution! Assigning the global environment worked. I also tried your list suggestion as it seems like lists are a better option based on your comment and the link you provided. However, when I use l[[Site]] <- rbindlist... the output is an empty list rather than containing one additional element that combines all the similar site data. I should note that when I import all the data, I'm doing so as a list (myfiles <- lapply(temp, fread), where temp calls the list.files function. Any idea what I might be missing? – bmdanhof Sep 05 '19 at 14:28
  • @bmdanhof I'm not sure, but if you posted a new question with a reproducible example that shows the issue, then I'm sure somebody can help out. Make sure your question includes sample data so users on this site can run the code and see the issue you're describing. – josliber Sep 05 '19 at 15:50