UCLA Academic Technology Services HomeServicesClassesContactJobs
Help the Stat Consulting Group by giving a gift             
Loading

R FAQ
How does R handle overlapping object names?

Because R is developed by an open source community, it is not uncommon that multiple packages may use the same name for a function or dataset. If you load packages that use the same name for an object, R will warn that certain object(s) have been "masked".

Spotting the Problem

Masking occurs when two or more packages have objects (such as functions) with the same name. Here is an example.

require(plyr)
Loading required package: plyr
require(reshape)
Loading required package: reshape

Attaching package: 'reshape'

The following object(s) are masked from 'package:plyr':

    rename, round_any

Dealing with Masking

Most of the time, masking is not a problem. However, there are times when you need to load multiple packages and a function you want to use becomes masked or you may even need to use a function with the same name from both packages. In these cases, there are several possibilities.

If you know you want to use the rename function in plyr, you can use a double colon to qualify the reference. For example:

plyr::rename
function (x, replace) 
{
    old_names <- names(x)
    new_names <- unname(replace)[match(old_names, names(replace))]
    setNames(x, ifelse(is.na(new_names), old_names, new_names))
}

Here you can see that the function definition is returned, and there is a note indicating that the environment is the namespace of the plyr package. The general form is package::function, so if we wanted to use the rename function from the reshape package:

reshape::rename
function (x, replace) 
{
    replacement <- replace[names(x)]
    names(x)[!is.na(replacement)] <- replacement[!is.na(replacement)]
    x
}

## change 'mpg' to 'NewName'
reshape::rename(head(mtcars), c(mpg = "NewName"))
                  NewName cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4            21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag        21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710           22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive       21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout    18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant              18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

Note that if we just type rename, R will return the value from the reshape package, because that package was loaded after the plyr package.

Typically, judicious loading of packages is preferred over explicit references. For day-to-day use, it is also common to load the package with the function you want to use last so that it's definition of the function masks those of the package(s) you do not want to use.

Another possibility is to use the get function. The get function takes as the first argument the name of the object (a function in this case) and then the location or environment of the object. Going back to our rename example:

get(x = "rename", pos = "package:plyr")
function (x, replace) 
{
    old_names <- names(x)
    new_names <- unname(replace)[match(old_names, names(replace))]
    setNames(x, ifelse(is.na(new_names), old_names, new_names))
}

It is more cumbersome, but a perfectly clear way to clarify where to get something. See the documentation for ?get for further details.

Technical Notes

When a package is loaded via library or require, it is automatically attached to the search path (typically in position 2). The first position is reserved for the global environment (i.e., the workspace where interactive commands are executed). When an object (function, data, etc.) is called from the command line, R first looks in the global environment, then proceeds up the search path until the object is found. If no instances exist, R reports that the object could not be found. The search path can be viewed using the search function. For example:

search()
 [1] ".GlobalEnv"        "package:reshape"   "package:plyr"     
 [4] "package:stats"     "package:graphics"  "package:grDevices"
 [7] "package:utils"     "package:datasets"  "package:methods"  
[10] "Autoloads"         "package:base"     

The order indicates the objects are searched for. Two similar functions, .packages and loadedNamespaces return a character vector of the names of loaded packages or namespaces, respectively. For example, in the session used to create this page:

> (.packages())
[1] "reshape"   "plyr"      "stats"     "graphics"  "grDevices" "utils"    
[7] "datasets"  "methods"   "base"     

> loadedNamespaces()
[1] "base"      "graphics"  "grDevices" "methods"   "plyr"      "reshape"  
[7] "stats"     "utils"    

Issues with masking and unclear references are one (of several) reason why it is not advised to use attach on a dataset. When a dataset is attached, it is added to the search path. As the number of variables in the dataset increases, the chance that some function or object in a package will be masked. Further, suppose that after attaching a dataset, a package is loaded. By default, the package gets added in position 2, while the dataset becomes position 3. Now if you call detach, it is the package, not the dataset that will be unattached. This is demonstrated below.

attach(mtcars)
search()
 [1] ".GlobalEnv"        "mtcars"            "package:reshape"  
 [4] "package:plyr"      "package:stats"     "package:graphics" 
 [7] "package:grDevices" "package:utils"     "package:datasets" 
[10] "package:methods"   "Autoloads"         "package:base"     

require(MASS)
Loading required package: MASS
search()
 [1] ".GlobalEnv"        "package:MASS"      "mtcars"           
 [4] "package:reshape"   "package:plyr"      "package:stats"    
 [7] "package:graphics"  "package:grDevices" "package:utils"    
[10] "package:datasets"  "package:methods"   "Autoloads"        
[13] "package:base"     

detach()
search()
 [1] ".GlobalEnv"        "mtcars"            "package:reshape"  
 [4] "package:plyr"      "package:stats"     "package:graphics" 
 [7] "package:grDevices" "package:utils"     "package:datasets" 
[10] "package:methods"   "Autoloads"         "package:base"     

Special Problems and Advanced References

Because of special environments for packages, masking is usually only a problem for users, not for packages themselves. However, if you notice a package is having problems finding the correct function, you should contact the package maintainer. Properly written packages do not have problems regardless of what other packages you attach, and the fix is straight forward for the package maintainer. To find out who the current maintainer is, you can use:

maintainer("plyr")
[1] "Hadley Wickham <h.wickham@gmail.com>"

where the first argument to the function is the name of the package in quotes. Note that the maintainer may be different from the author, and the maintainer is the correct individual to contact.

Partly to reduce confusion and problems of masking, R packages have a namespace. This is just a special environment (you can think of it like a filing cabinet) that belongs all to that package. Authors have a choice what functions or objects from their package are made publically available and which are only available internally. With masked object(s), the problem was the wrong object was used. With internal (non exported) objects, R will say that it cannot find the object. If you want to look at or use an internal object, you can use the triple colon operator, ":::". Note that ":::" also qualifies the reference with the package name (as the double colons "::" did), so there can be no confusion about where it came from. Below is an example using the plyr package. id_var is an internal function in plyr, to access it, we would need to use the package:::function syntax, as below.

id_var
Error: object 'id_var' not found
plyr:::id_var
function (x, drop = FALSE) 
{
    if (length(x) == 0) 
        return(structure(integer(), n = 0))
    if (!is.null(attr(x, "n")) && !drop) 
        return(x)
    if (is.factor(x) && !drop) {
        id <- as.integer(addNA(x, ifany = TRUE))
        n <- length(levels(x))
    }
    else {
        levels <- sort(unique(x), na.last = TRUE)
        id <- match(x, levels)
        n <- max(id)
    }
    structure(id, n = n)
}


How to cite this page

Report an error on this page or leave a comment

UCLA Researchers are invited to our Statistical Consulting Services
We recommend others to our list of Other Resources for Statistical Computing Help
These pages are Copyrighted (c) by UCLA Academic Technology Services


The content of this web site should not be construed as an endorsement of any particular web site, book, or software product by the University of California.