18

In python I can load a specific function or functionality with:

from x import y as z

How can I replicate this in R?

For instance, I want to load just the count function from plyr, instead of loading the entire package with library(plyr)

emehex
  • 9,874
  • 10
  • 54
  • 100
  • 3
    You could do `plyr::count()`. This will give you access to the function without loading the package. – eipi10 May 19 '15 at 19:47
  • 1
    @Gregor: they're not quite the same. The question you reference is about importing an entire package under a different name, whereas this is asking how to import one function from a package and give the function a different name. – Joshua Ulrich May 19 '15 at 20:03
  • 2
    Agreed, Josh. I'll let my close vote expire and instead just say 'closely related: ["import as" in R](http://stackoverflow.com/q/24391251/903061)' – Gregor Thomas May 19 '15 at 20:19

6 Answers6

21

I'd probably just do count <- plyr::count, so I wouldn't have to bother with ensuring I get the arguments correct.

And you might want to wrap that definition in an if statement, in case plyr isn't installed:

if (requireNamespace("plyr"))
    count <- plyr::count
else
    stop("plyr is not installed.")

Also you might be interested in the import and/or modules packages, which provide python-like import/module mechanisms for R.


Also heed the warning from the Adding new generics section of Writing R Extensions (original emphasis):

Earlier versions of this manual suggested assigning foo.default <- base::foo. This is not a good idea, as it captures the base function at the time of [package] installation and it might be changed as R is patched or updated.

So it would be okay to use the count <- plyr::count syntax if it's defined in a script you're sourceing, but you should explicitly define a new function and specify all the arguments if you do this in a package.

Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
  • Nice, why not in the `else` have `{install.packages("plyr"); count <- plyr::count}` – dimitris_ps May 19 '15 at 20:53
  • 4
    @dimitris_ps: You could, but I was thinking of a situation where my code would be wrapped in some other function, in which case I wouldn't want it to go off downloading things. – Joshua Ulrich May 19 '15 at 21:02
11

from plyr import count as count could look like this:

count <- function(x) {
    plyr::count(x)
}

Simplified:

count <- plyr::count

More complete:

if (requireNamespace("plyr")) 
    count <- plyr::count

EDIT:

I was inspired by @eipi10's comment. I was unaware of ::
Thanks @Joshua Ulrich for the suggestions!

emehex
  • 9,874
  • 10
  • 54
  • 100
  • 4
    I'd probably just do `count <- plyr::count`, so I wouldn't have to bother with ensuring I get the arguments correct. And you might want to wrap that definition in an if statement, in case plyr isn't installed: `if (requireNamespace("plyr")) count <- plyr::count`. – Joshua Ulrich May 19 '15 at 19:53
6

There is no directly equivalent functionality in R, though as the other answers have noted, you can obtain similar results.

The library argument both loads the package namespace and attaches it to the search list. As noted by Joshua Ulrich it is possible to load a package namespace without attaching the namespace to the search list. Using library actually calls both loadNamespace and attachNamespace.

The distinction of loading vs. attaching is best explained by someone who has extensive package development expertise (the aforementioned Mr. Ulrich comes to mind) so I suggest reading further in this write-up on namespaces by Hadley Wickham.

Worth noting, however, is that you can use the pos argument in library() to define where you are attaching the package namespace, as explained in the documentation for the library statement.

Community
  • 1
  • 1
TARehman
  • 6,659
  • 3
  • 33
  • 60
  • 3
    This isn't quite true. Packages are *attached* or *unattached* to the search path in their entirety, but they do not have to be attached to be used. A package namespace can be loaded without being attached. – Joshua Ulrich May 19 '15 at 19:51
  • I see what you mean. I am a little out of my depth here; could you do an edit that clarifies this? I don't want to post false information on this and always tend to cross my wires on _attaching_ vs. _loading_. – TARehman May 19 '15 at 19:53
  • Take a look at `?requireNamespace` and my comment to the OP's self-answer. Bah, I should probably just write an answer... :) – Joshua Ulrich May 19 '15 at 19:55
  • You are the expert here, but I tried to expand on it a little bit above to be more correct and to stem the tide of downvotes. :D – TARehman May 19 '15 at 20:18
2

I just stumbled across this question looking for the same functionality and using the approach described above, wrote a quick function to generalize the idea. I wanted to post it here for anyone who came across this question in the future.

import <- function(pkg, f) {
  if (pkg %in% installed.packages()) {
    assign(f, eval(parse(text = paste(pkg, "::", f, sep = ""))), envir = .GlobalEnv)
  } else {
    stop(paste(pkg, "is not installed."))
  }
}
tblznbits
  • 6,602
  • 6
  • 36
  • 66
2

You can use the built-in library() function with the include.only parameter.

library(plyr, include.only = c("count"))

# Okay
count(mtcars, vars = "cyl")
#>   cyl freq
#> 1   4   11
#> 2   6    7
#> 3   8   14

# Fails to find plyr::arrange()
arrange(mtcars, cyl, disp)
#> Error in arrange(mtcars, cyl, disp): could not find function "arrange"

Created on 2021-02-09 by the reprex package (v0.3.0)

Eric Leung
  • 2,354
  • 12
  • 25
2

There’s now a package which provides this exact functionality: ‘box’.1 With it, the R equivalent of Python’s from x import y as z is:

box::use(x[z = y])

For instance, I want to load just the count function from plyr, instead of loading the entire package with library(plyr)

box::use(plyr[count])

It’s also worth noting that, unlike library(), box::use() attaches names locally. For example, to attach all names of a package inside a function without affecting the global search path, you can write

f = function () {
    box::use(plyr[...])
    # use it here.
}

([...] is tells box::use() to attach all names.)

It’s worth noting that as of R 3.6, library also supports attaching only specified names:

library(plyr, include.only = 'count')

However, this still performs global attaching, it doesn’t allow aliases (i.e. I can’t import plyr::count as, say, plyr_count), and calling library repeatedly with the same package name but different include.only lists doesn’t work (subsequent calls have no effect). In other words, it does strictly less than the Python import mechanism or box::use().


1 This package is the successor to the ‘modules’ package mentioned in Joshua’s answer, but it uses a completely different syntax and has more features.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214