From ripley at stats.ox.ac.uk  Sat Mar  6 21:17:23 2010
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Sat, 6 Mar 2010 20:17:23 +0000 (GMT)
Subject: [Rd] Defining a method in two packages
In-Reply-To: <4B92A2C9.1020803@statistik.tu-dortmund.de>
References: <1267807677.9076.21.camel@punchbuggy>
	<4B92A2C9.1020803@statistik.tu-dortmund.de>
Message-ID: <alpine.LFD.2.00.1003061952170.14938@gannet.stats.ox.ac.uk>

On Sat, 6 Mar 2010, Uwe Ligges wrote:

> Terry,
>
> this happens since the ranef in coxme is a S3 generic and the one in lme4 is 
> a S4 generic.

But the packages could be more cooperative.  There is also a S3 
generic for ranef in package nlme.  Ideally the S4 generic in lme4 
would have a default method which dispatched on S3 methods: that would 
be easy to achieve if there was just one other ranef, but not so if 
there are 2 or more -- but read on.

Indeed, the situation is pretty much the same if you load nlme after 
coxme:

> library(nlme)

Attaching package: 'nlme'

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

     fixed.effects, fixef, random.effects, ranef

> ranef(fit)
Error in UseMethod("ranef") :
   no applicable method for 'ranef' applied to an object of class "coxme"

The situation can be alleviated by making S3 methods visible.  Thus if
coxme exported coxme:::ranef.coxme and lme4 had a default method

function (object, ...) UseMethod("ranef")

loading lme4 (or nlme) after coxme would work.

My solution would though be NOT to reuse a name that is already 
established in another package (nlme has used it for many years).

The design problem is that generic foo() in package B might have 
nothing to do with foo() in package A.  When it does, we expect B to 
import the generic from A, but that can be a 'which came first' 
problem unless a base package is involved.  But here nlme is a 
long-established recommended package, so it would be reasonable to 
expect both coxme and lme4 to import from it.


> Of course, after loading lme4, you can still use the ranef from coxme:
>
> coxme::ranef(fit)
>
> and get the desired result.
>
> If you write your own code, you might want to use that call explicitly (i.e. 
> accessing from the correct namepsace). In your own package, you could simply 
> import the generic from coxme.

> Best wishes,
> Uwe
>
>
>
>
>
>
> On 05.03.2010 17:47, Terry Therneau wrote:
>> The coxme package has a ranef() method, as does lme4.  I'm having
>> trouble getting them to play together, as shown below.  (The particular
>> model in the example isn't defensible, but uses a standard data set.)
>> 
>> The problem is that most of the time only one of lme4 or coxme will be
>> loaded, so each needs to define the basic ranef function as well as a
>> method for it.  But when loaded together the last one wins.  The coxme
>> object is an S3 class BTW. (Suggestions to convert it to S4 will not be
>> well recieved -- but that's a different and unnecessary thread.)
>> 
>> Odds are that this has a simple solution which I have missed.
>>       Terry Therneau
>> 
>> 
>> tmt935% R --vanilla
>> 
>> R version 2.10.0 (2009-10-26)
>> Copyright (C) 2009 The R Foundation for Statistical Computing
>> ISBN 3-900051-07-0
>> 
>> R is free software and comes with ABSOLUTELY NO WARRANTY.
>> You are welcome to redistribute it under certain conditions.
>> Type 'license()' or 'licence()' for distribution details.
>>
>>    Natural language support but running in an English locale
>> 
>> R is a collaborative project with many contributors.
>> Type 'contributors()' for more information and
>> 'citation()' on how to cite R or R packages in publications.
>> 
>> Type 'demo()' for some demos, 'help()' for on-line help, or
>> 'help.start()' for an HTML browser interface to help.
>> Type 'q()' to quit R.
>> 
>>> library(coxme)
>> Loading required package: survival
>> Loading required package: splines
>> Loading required package: bdsmatrix
>> 
>>> fit<- coxme(Surv(time, status) ~ age + (1|ph.ecog), lung)
>>> ranef(fit)
>> $ph.ecog
>> Intercept
>> 0.1592346
>> 
>>> library(lme4)
>> Loading required package: Matrix
>> Loading required package: lattice
>> 
>> Attaching package: 'lme4'
>> 
>>
>>          The following object(s) are masked from package:coxme :
>>
>>           fixef,
>>           ranef
>> 
>>> ranef(fit)
>> Error in function (classes, fdef, mtable)  :
>>    unable to find an inherited method for function "ranef", for signature
>> "coxme"
>>> q()
>> 
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

-- 
Brian D. Ripley,                  ripley at stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595



[Rd] Defining a method in two packages
Prof Brian Ripley