Farid Cheraghi
Farid Cheraghi

Reputation: 747

use functions in another package without attaching to the search path?

I use pkgs::function notation to access a function in another package. This sometimes cause a problem like this one from survival package:

data(logan,package="survival")
resp <- levels(logan$occupation)
n <- nrow(logan)
indx <- rep(1:n, length(resp))
logan2 <- data.frame(logan[indx,],
                     id = indx,
                     tocc = factor(rep(resp, each=n)))
logan2$case <- (logan2$occupation == logan2$tocc)
survival::clogit(case ~ tocc + tocc:education + survival::strata(id), logan2)

it gives error: Error in eval(expr, envir, enclos) : could not find function "coxph"

coxph is another function called internally from clogit function. Can this situation be avoided? I don't want to attach the package to the search path i.e. using library(survival) as per Hadley's advanced r best practices.

Upvotes: 3

Views: 282

Answers (2)

Ben Bolker
Ben Bolker

Reputation: 226182

(Amplifying @RichScriven's comment above.)

I'm not entirely sure where in Advanced R you're getting "don't use library()" as a best practice. Maybe in the Functions section (please edit your question to clarify if I have the wrong bit!) where it says:

The functions that are the easiest to understand and reason about are pure functions: functions that always map the same input to the same output and have no other impact on the workspace. In other words, pure functions have no side effects: they don't affect the state of the world in any way apart from the value they return.

... [points out that library() is an impure function because it changes the search path] ...

It's generally a good idea to minimise the use of side effects, and where possible, to minimise the footprint of side effects by separating pure from impure functions.

Note the loose wording here: "It's generally a good idea to minimise ... where possible, to minimise ..." This doesn't mean "don't ever use library()" ... It makes sense that you wouldn't want to put library() inside a function, or inside a package. If you're using a package, you can (should?) use @importFrom survival clogit coxph instead ... I find that putting the @importFrom tags at the beginning of each of my functions works well enough to tag the external functions being used therein that I don't necessarily need :: to identify foreign functions (your mileage may vary).

However, if you're actually writing code to do a survival analysis then bending over backwardsgoing to great lengths to avoid library(survival) seems unnecessary.

Amplifying @PierreLafortune's comment above: clogit internally contains the code coxcall[[1]] <- as.name("coxph"). Your code would probably work as is if this line were changed to coxcall[[1]] <- as.name("survival::coxph"). You could post an issue request on Github about this if you felt strongly enough ...

Upvotes: 4

CCurtis
CCurtis

Reputation: 1932

Just do survival::coxph->coxph. Here you're just creating a new function in the environment with the same name so clogit should find the new function.

Upvotes: 0

Related Questions