[R] Survfit error

Hadley Wickham h.wickham at gmail.com
Fri Mar 7 16:45:56 CET 2014


On Fri, Mar 7, 2014 at 6:46 AM, Therneau, Terry M., Ph.D.
<therneau at mayo.edu> wrote:
>>> The help page for the survfit function says it expects a formula as its
>>> first argument so try:
>>>
>>> > sleepfit <- survfit(Surv(timeb, death)~1, data = sleep)
>>>
>>> David
>>> Sent from my iPhone ... so unable to test.
>>>
>>>
>> This was a recent (well, 2007) change in behaviour. Previously the
>> function
>> did some tricks to make either approach work, which could be described as
>> 'clever' or 'too clever by half'.
>>
>>   -thomas
>
>
>  Certainly the latter, a design mistake that I finally admitted and
> corrected.  The trouble is this usage
>      fit <- survfit(Surv(time, status), data=mine)
>
> The data, subset, weights, and na.action arguments are all meant to work
> with formulas. The first argument above isn't a formula.  This left survfit
> with the quandry of how to recognize that the first argument is a "Surv"
> object and not a formula, and do something differently.  Which leads to a
> stalemate
>         a. One doesn't know what type of object the first argument is until
> it is evaluated
>         b. Evaluation will fail, however, unless it is evaluated in the
> "data=mine" context
>         c. The function that does that process (model.frame) expects a
> formula as its first arg
>
> My program needed to know the answer to a) in order to transform the first
> arg into a formula and correctly execute c), but needed the answer from c)
> to know if that was necessary.
>
> The old code peeked back at the actual string that was typed by the user,
> looking for the letters "Surv", but was easily fooled.

It's not possible to be perfect in this scenario, but you could use
some heuristics:


survfit <- function(x, ...) {
  xq <- substitute(x)
  if (!is.call(xq)) {
    stop("First argument to survfit must be a function call")
  }

  if (identical(xq[[1]], quote(Surv))) {
    "surv"
  } else if (identical(xq[[1]], quote(`~`))) {
    "formula"
  } else {
    "don't know"
  }
}

survfit(Surv(time, status), data=mine)
survfit(Surv(timeb, death)~1, data = sleep)


You'd need a different heuristic if is.name(xq) is TRUE, indicating
that the user passed in the name of an existing variable.

Hadley


-- 
http://had.co.nz/




More information about the R-help mailing list