D. Studer
D. Studer

Reputation: 1885

Access global variable within function

I have two data.frames df1 and errors and a function add_to_errors(). The argument of the function is a vector of row-numbers (of df1) and the function should add add the row selected to a new data.frame called errors.

df1 <- data.frame(id=1:10,
                  var1=rep(NA, 2),
                  var2=rep(NA, 2))

errors <- data.frame()

add_to_errors <- function(ids){
    rows_to_add <- df1[ids,]
    errors <- rbind(errors, rows_to_add)
    return(errors)
} 

add_to_errors(c(1,2))
add_to_errors(c(6,7))

When I execute add_to_errors(1, 2) and add_to_errors(6,7), it looks as if errors was overwritten each time the function is called. How can I access errors as a global variable within the function?

The output should look like this:

  id var1 var2
1  1   NA   NA
2  2   NA   NA
3  6   NA   NA
4  7   NA   NA 

Upvotes: 1

Views: 1332

Answers (2)

LyzandeR
LyzandeR

Reputation: 37889

One way would be to use <<-, like this:

add_to_errors <- function(ids){
  rows_to_add <- df1[ids,]
  errors <<- rbind(errors, rows_to_add)
  return(errors)
} 

add_to_errors(c(1,2))
#  id var1 var2
#1  1   NA   NA
#2  2   NA   NA
add_to_errors(c(6,7))
#  id var1 var2
#1  1   NA   NA
#2  2   NA   NA
#6  6   NA   NA
#7  7   NA   NA

Changing the global environment through <<- within a function is not considered good practice (this is called side effect and it's better to be avoided - if possible - as it creates bugs).

Upvotes: 1

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522762

I recommend not using the parent scope operator <<-, and instead using your function with proper design and encapsulation:

add_to_errors <- function(df1, ids, errors) {
    rows_to_add <- df1[ids,]
    errors <- rbind(errors, rows_to_add)
    return(errors)
}

df1 <- data.frame(id=1:10, var1=rep(NA, 2), var2=rep(NA, 2))
errors <- data.frame()
errors <- add_to_errors(df1, c(1,2), errors)
errors <- add_to_errors(df1, c(6,7), errors)
errors

  id var1 var2
1  1   NA   NA
2  2   NA   NA
6  6   NA   NA
7  7   NA   NA

The above functions has been refactored to accept all needed parameters as inputs, and the output is the data frame generated using your logic. When calling it, we clobber (overwrite) the input data frame with the return value.

Upvotes: 5

Related Questions