Search code examples
rrm

Why doesn't rm() work on paste0() string?


I tried removing data from my environment using rm(paste0("namePart1", "namePart2")), but got the " ... must contain names or character strings" error. However, when I changed it to rm(list=paste0("namePart1", "namePart2")) or rm("namePart1namePart2") the problem disappeared. What is the difference?


Solution

  • The answer is in the documentation of rm, last paragraph of section Details, my emphasis.

    Earlier versions of R incorrectly claimed that supplying a character vector in ... removed the objects named in the character vector, but it removed the character vector. Use the list argument to specify objects via a character vector.

    1. Pass the variables' names as character strings one by one.

    No errors are thrown, the objects x1, x2 and x3 were removed from the .GlobalEnv.

    x1 <- 1
    x2 <- 2
    x3 <- 3
    
    rm(x1)         # or rm("x1")
    rm(x2, x3)     # or rm("x2", "x3")
    

    Created on 2022-10-03 with reprex v2.0.2

    2. Pass a character vector containing the objects' names.

    What is removed is the vector vec, the objects whose names it used to contain still exist in the .GlobalEnv.

    x1 <- 1
    x2 <- 2
    x3 <- 3
    vec <- c("x2", "x3")
    
    rm("vec")
    
    x1
    #> [1] 1
    x2
    #> [1] 2
    x3
    #> [1] 3
    
    vec
    #> Error in eval(expr, envir, enclos): object 'vec' not found
    

    Created on 2022-10-03 with reprex v2.0.2

    3. Dynamically create names of objects to be removed.

    Functions paste and paste0 both return vectors and for the documented reasons above rm doesn't remove objects with names returned by a function, it tries to remove the character vector but it cannot because the dots argument only accepts unquoted names or character strings naming objects.

    The users need to dynamically create names of objects to be removed is predicted and that's why argument list exists. In order to remove the objects, not the vector containing their names, use list = vec. Now vec can be the output of a function such as paste, paste0 or ls.

    x1 <- 1
    x2 <- 2
    x3 <- 3
    
    paste0("x", 1:3)
    #> [1] "x1" "x2" "x3"
    
    rm(paste0("x", 1:3))
    #> Error in rm(paste0("x", 1:3)):  
    #>   ... must contain names or character strings
    
    rm(list = paste0("x", 1:3))
    
    x1
    #> Error in eval(expr, envir, enclos): object 'x1' not found
    x2
    #> Error in eval(expr, envir, enclos): object 'x2' not found
    x3
    #> Error in eval(expr, envir, enclos): object 'x3' not found
    

    Created on 2022-10-03 with reprex v2.0.2