1

I have written a function to get the name and version of all of my loaded packages:

my_lib <- function(){

  tmp <- (.packages())
  tmp_base <- sessionInfo()$basePkgs
  tmp <- setdiff(tmp, tmp_base)

  tmp <- sort(tmp)
  tmp <- sapply(tmp, function(x){
    x <- paste(x, utils::packageVersion(x), sep = ' v')
  })
  tmp <- paste(tmp, collapse=', ')

  return(tmp)
}

This also returns all packages loaded as dependencies to other packages (eg I load car and carData is loaded as a dependency).

I am wondering if there is a way to only return the packages I manually loaded (eg just car)? Can R tell the difference between manually loaded vs loaded as a dependency?

Edit:

Added line to remove base packages using sessionInfo()

morgan121
  • 2,213
  • 1
  • 15
  • 33
  • 5
    If you look at `sessionInfo()`, it distinguishes between `other attached packages:` and `loaded via a namespace (and not attached):`. But I think some package authors will load their dependencies by attaching them, so you may get some dependencies showing up as attached packages. – Marius Jun 13 '19 at 23:48
  • 1
    thanks! I have added a bit to remove the base packages from the list using `sessionInfo()` now. I think most of the dependencies I use must be attached because they all show in the `other attached package` section :P – morgan121 Jun 14 '19 at 00:04
  • 1
    In general, I think best practice is for packages to only load and not attach their dependencies, but it's not a hard and fast rule (see http://r-pkgs.had.co.nz/namespace.html). So it might not be possible to distinguish clearly between loaded packages/dependencies this way. RStudio now does some automatic suggestions when it can see the packages that are used in a script aren't installed, it might just be scanning the script for `library()` calls, which might be another way to do this. – Marius Jun 14 '19 at 00:12
  • that was my first thought too (the scanning for library) but often we do our data prep in a different file and `source` it, and that is where the majority of libraries are called. I guess I could scan for a `source` command, then the corresponding file, but it would be much harder as we also source functions. – morgan121 Jun 14 '19 at 00:15
  • 1
    @RAB I *just* thought of a possibility to track usage with a custom function, and updated my original answer accordingly. Better late than never, right? – Alexis Sep 24 '19 at 20:45

1 Answers1

1

R has a subtle difference between a loaded package and an attached package. A package is attached when you use the library function, and it makes its exported functions "visible" to the user's global environment. If a package is attached, its namespace has been loaded, but the opposite is not necessarily true.

Each package can define two main types of dependencies: Depends and Imports. The packages in the former get attached as soon as the dependent package is attached, but the packages in the latter only get loaded.

This means you can't completely differentiate, because you may call library for a specific package, but any packages it Depends on will also be attached. Nevertheless, you can differentiate between loaded and attached packages with loadedNamespaces() and search().

EDIT: It just occurred to me that if you want to track usage of library (ignoring require), you could write a custom tracker:

library_tracker <- with(new.env(), {
  packages <- character()

  function(flag) {
    if (missing(flag)) {
      packages <<- union(packages, as.character(substitute(package, parent.frame())))
    }

    packages
  }
})

trace("library", library_tracker, print = FALSE)

library("dplyr")
library(data.table)

# retrieve packages loaded so far
library_tracker(TRUE)
[1] "dplyr"      "data.table"

The flag parameter is just used to distinguish between calls made by trace, which call the function without parameters, and those made outside of it, in order to easily retrieve packages loaded so far. You could also use environment(library_tracker)$packages.

Alexis
  • 4,950
  • 1
  • 18
  • 37