How to Find the Package Name in R for a Specific Function

How to get the package name of a function in R?

Perhaps even most convenient, if you are just after the package name:

environmentName(environment(select))

The advantage is that this produces a string rather than an environment object.

Name of a package for a given function in R

There may be better solutions, but find("functionname") seems to work reasonably well? However, it only works for loaded packages.

> find("strwidth")
[1] "package:graphics"
> find("qplot")
character(0)
> library(ggplot2)
> find("qplot")
[1] "package:ggplot2"
>

(If you need the raw name of the package you can use gsub("^package:","",results))

(The answers to the previous question linked by Andrie include this answer; they don't give the bit about gsub, and they all seem to share the issue of not finding non-loaded packages.)

Here's a quick hack to find functions even in non-loaded packages:

findAllFun <- function(f) {
h <- help.search(paste0("^",f,"$"),agrep=FALSE)
h$matches[,"Package"]
}

findAllFun("qplot")
## "ggplot2"
findAllFun("lambertW")
## "emdbook" "VGAM"
> findAllFun("xYplot")
## "Hmisc" "lattice"

If you need to find functions in non-installed packages (i.e. searching CRAN), then findFn from the sos package will be your friend.

Finding a function of a specific package in RStudio help pane

RStudio HelpPane

Today the RStudio java code for help Window (see -> HelpPane.java:364) does not support the ability to search a specific package context. It could but it would require modifications to HelpSearch.java:67

./rstudio/src/gwt/src/org/rstudio/studio/client/workbench/views/help

./HelpPane.java:364:
toolbar.addRightWidget(searchProvider_.get().getSearchWidget());
./search/HelpSearch.java:67:
public Widget getSearchWidget()

RStudio

Today, in RStudio you can do a help lookup via the R console and reflect the results in the RStudio help window. The workaround is to type ?dplyr::count in the R Console and have this reflected in the RStudio help window.

Sample Image

I hope the above information if useful, and points you in the right direction. My sense is you'll need to request or change RStudio window behaviour.


R Help Observations:

If you wish to look up a specific function in a package you can use the following syntax:

help(count, package="dplyr")

Personally, I also recommend using the sos library which adds ??? this enables access to the findfn() and ??? which enables you to access RSiteSearch() and search across all CRAN libraries for a function.

> require(sos)
>
> ???count
found 7174 matches; retrieving 20 pages, 400 matches.
2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20

Downloaded 399 links in 244 packages.

The above syntax is referenced in the R documentation. https://www.r-project.org/help.html

R Help: help() and ?

The help() function and ? help operator in R provide access to the documentation pages for R functions, data sets, and other objects, both for packages in the standard R distribution and for contributed packages. To access documentation for the standard lm (linear model) function, for example, enter the command help(lm) or help("lm"), or ?lm or ?"lm" (i.e., the quotes are optional).

To access help for a function in a package that’s not currently loaded, specify in addition the name of the package: For example, to obtain documentation for the rlm() (robust linear model) function in the MASS package, help(rlm, package="MASS").

Standard names in R consist of upper- and lower-case letters, numerals (0-9), underscores (_), and periods (.), and must begin with a letter or a period. To obtain help for an object with a non-standard name (such as the help operator ?), the name must be quoted: for example, help('?') or ?"?".

You may also use the help() function to access information about a package in your library — for example, help(package="MASS") — which displays an index of available help pages for the package along with some other information.

Help pages for functions usually include a section with executable examples illustrating how the functions work. You can execute these examples in the current R session via the example() command: e.g., example(lm).

R - how to identify which version (package) of a function is active/attached?

You can find out which functions are in conflict (being masked) by using conflicts(detail = TRUE). This returns a named list of packages / functions in conflict in the order of the search() path which is the order in which they will be called.

As an example, we can load dplyr which loads some functions that conflict with base.

library(dplyr)

# Create data.frame of conflicts and clean up.
conf <- conflicts(detail = TRUE)
conf.df <- data.frame(do.call(rbind, Map(cbind, conf, names(conf))))
names(conf.df) <- c("fn", "package")
conf.df$package <- sub("package:", "", conf.df$package)

# Aggregate packages by function - first package is the default when called.
aggregate(package ~ fn, conf.df, toString)

fn package
1 body<- methods, base
2 filter dplyr, stats
3 intersect dplyr, base
4 kronecker methods, base
5 lag dplyr, stats
6 setdiff dplyr, base
7 setequal dplyr, base
8 union dplyr, base

R How to check that a custom function is called within a specific function from a certain package

Update: I'm going to "borrow" from rlang::trace_back, since it seems to have an elegant (and working) method for determining a full package::function for most of the call tree (some like %>% are not always fully-resolved).

(If you're trying to reduce package bloat ... while it's unlikely you'd have dplyr and not purrr available, if you would prefer to do as much in base as possible, I've provided #==# equivalent base-R calls. It's certainly feasible to try to remove some of the rlang calls, but again ... if you're assuming dplyr, then you definitely have rlang around, in which case this should not be a problem.)

EDIT (2022-02-25): the function below uses ::: functions in rlang, which (not surprisingly) no longer exist as of today, as a clear example of why using :::-funcs is inherently risky. This function no longer works. I'm not going to attempt to fix now (no immediate need/motivation). Cheers.

search_calling_pkg <- function(pkgs, funcs) {
# <borrowed from="rlang::trace_back">
frames <- sys.frames()
idx <- rlang:::trace_find_bottom(NULL, frames)
frames <- frames[idx]
parents <- sys.parents()[idx]
calls <- as.list(sys.calls()[idx])
calls <- purrr::map(calls, rlang:::call_fix_car)
#==# calls <- lapply(calls, rlang:::call_fix_car)
calls <- rlang:::add_pipe_pointer(calls, frames)
calls <- purrr::map2(calls, seq_along(calls), rlang:::maybe_add_namespace)
#==# calls <- Map(rlang:::maybe_add_namespace, calls, seq_along(calls))
# </borrowed>
calls_chr <- vapply(calls, function(cl) as.character(cl)[1], character(1))
ptn <- paste0("^(", paste(pkgs, collapse = "|"), ")::")
pkgres <- any(grepl(ptn, calls_chr))
funcres <- !missing(funcs) && any(mapply(grepl, paste0("^", funcs, "$"), list(calls_chr)))
if (!pkgres || !funcres) {
stop("not correct")
} else return()
}

The intention is that you can look for particular packages and/or particular functions. The funcs= argument can be fixed strings (taken as verbatim), but since I thought you might want to match against any of the mutate* functions (etc), you can also make it a regex. All functions need to be full package::funcname, not just funcname (though you could certainly make it a regex :-).

myfun1 <- function() {
search_calling_pkg(pkgs = "dplyr")
NULL
}
myfun2 <- function() {
search_calling_pkg(funcs = c("dplyr::mutate.*", "dplyr::summarize.*"))
NULL
}
mutate <- function(df, x) { force(x); NULL; }
mtcars[1:2,] %>% mutate(myfun1())
# Error: not correct

mtcars[1:2,] %>% dplyr::mutate(myfun1())
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1 21 6 160 110 3.9 2.620 16.46 0 1 4 4
# 2 21 6 160 110 3.9 2.875 17.02 0 1 4 4

mtcars[1:2,] %>% mutate(myfun2())
# Error: not correct

mtcars[1:2,] %>% dplyr::mutate(myfun2())
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1 21 6 160 110 3.9 2.620 16.46 0 1 4 4
# 2 21 6 160 110 3.9 2.875 17.02 0 1 4 4

And performance seems to be significantly better than the first answer, though still not a "zero hit" on performance:

microbenchmark::microbenchmark(
a = mtcars %>%
dplyr::mutate(),
b = mtcars %>%
dplyr::mutate(myfun1())
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# a 1.5965 1.7444 1.883837 1.82955 1.91655 3.0574 100
# b 3.4748 3.7335 4.187005 3.92580 4.18140 19.4343 100

(This portion kept for prosperity, though note that getAnywhere will find dplyr::mutate even if the above non-dplyr mutate is defined and called.)

Seeded by Rui's links, I suggest that looking for specific functions might very well miss new functions and/or otherwise-valid but differently-named functions. (I don't have a clear example.) From here, consider looking for particular packages instead of particular functions.

search_calling_pkg <- function(pkgs) {
call_st <- lapply(sys.calls(), `[[`, 1)
res <- any(vapply(call_st, function(ca) any(pkgs %in% tryCatch(getAnywhere(as.character(ca)[1])$where, error=function(e) "")), logical(1)))
if (!res) {
stop("not called from packages")
} else return()
}
myfun <- function() {
search_calling_pkg("package:dplyr")
NULL
}

Realize that this is not an inexpensive operation. I believe the majority of time spent in this is dealing with the calling tree, perhaps not something we can easily remedy.

microbenchmark::microbenchmark(
a = mtcars %>% mutate(),
b = mtcars %>% mutate(myfun())
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# a 1.872101 2.165801 2.531046 2.312051 2.72835 4.861202 100
# b 546.916301 571.909551 603.528225 589.995251 612.20240 798.707300 100

If you believe it will be called infrequently and your function takes "a little time", then perhaps the half-second delay won't be that noticeable, but with this toy example the difference is palpable.

R: 2 functions with the same name in 2 different packages

You have probably already noticed that the order of loading the packages makes a difference, i.e. the package that gets loaded last will mask the functions in packages loaded earlier.

To specify the package that you want to use, the syntax is:

chron::is.weekend()
tseries::is.weekend()

In other words, use packagename::functionname()

In addition, if you know that you will always want to use the function in chron, you can define your own function as follows:

is.weekend <- chron::is.weekend    #EDIT

R: Get function name called with package::function as string in R

I think substitute could be your friend. From the docs:

substitute returns the parse tree for the (unevaluated) expression expr

This allows you to access the (unevaluated) expression pack::foo inside your function.

The following produces your desired outcome:

giveArgumentFunctionName <- function(func) {
function.name <- as.character(substitute(func))[[3]]
return (function.name)
}

giveArgumentFunctionName(pack::foo)
# [1] "foo"
giveArgumentFunctionName(pack::bar)
# [1] "bar"


Related Topics



Leave a reply



Submit