[Rd] specials and ::
Duncan Murdoch
murdoch@dunc@n @end|ng |rom gm@||@com
Mon Aug 26 18:58:06 CEST 2024
On 2024-08-26 12:34 p.m., Duncan Murdoch wrote:
> On 2024-08-26 10:42 a.m., Therneau, Terry M., Ph.D. via R-devel wrote:
>> The survival package makes significant use of the "specials" argument of terms(), before
>> calling model.frame; it is part of nearly every modeling function. The reason is that
>> strata argments simply have to be handled differently than other things on the right hand
>> side. Likewise for tt() and cluster(), though those are much less frequent.
>>
>> I now get "bug reports" from the growing segment that believes one should put
>> packagename:: in front of every single instance. For instance
>> fit <- survival::survdiff( survival::Surv(time, status) ~ ph.karno +
>> survival::strata(inst), data= survival::lung)
>>
>> This fails to give the correct answer because it fools terms(formula, specials=
>> "strata"). I've stood firm in my response of "that's your bug, not mine", but I begin
>> to believe I am swimming uphill. One person responded that it was company policy to
>> qualify everything.
>>
>> I don't see an easy way to fix survival, and even if I did it would be a tremendous amout
>> of work. What are other's thoughts?
>
> I received a similar complaint about the tables package, which had
> assumed during argument processing that it was on the search list in
> order to find a function (see
> https://github.com/dmurdoch/tables/issues/30 if you want the details).
> In my case there's only one function exported by tables that wasn't
> being found, "labelSubset".
>
> I don't know any of the details of the survival problems. When I try
> your example code above without attaching survival, it appears to work.
> So my solution might be irrelevant to you.
>
> The way I found to work around this was to use this code early in the
> processing, when it is trying to turn the data argument into an environment:
>
> parent <- if (is.environment(data)) data else environment(table)
> if (!exists("labelSubset", envir = parent)) {
> withTableFns <- new.env(parent = parent)
> withTableFns$labelSubset <- labelSubset
> } else
> withTableFns <- parent
>
> if (is.null(data))
> data <- withTableFns
> else if (is.list(data))
> data <- list2env(data, parent = withTableFns)
> else if (!is.environment(data))
> stop("'data' must be a dataframe, list or environment")
Of course, posting this meant I discovered a bug in it: if
is.environment(data) was TRUE, the modification was ignored. Line 8
should be
if (is.null(data) || is.environment(data))
to handle that case.
Duncan Murdoch
>
> This inserts a new environment containing just that one tables function.
>
> One issue is if a user has "labelSubset" already in the environment; I
> decided to use that one on the assumption that the user did it
> intentionally. It would have been better to use a name that was less
> likely to show up in another package, but it's old code.
>
> This isn't on CRAN yet, so I'd be interested in hearing about problems
> with this approach, or better solutions.
>
> Duncan Murdoch
More information about the R-devel
mailing list