2014-12-30 11 views
8

Un collega mi ha chiesto questo, e ho faticato con esso.passaggio di espressioni a curve() all'interno di una funzione

Supponiamo di voler definire una funzione che prende un'espressione (diciamo x^2 per concretezza) come argomento e passa tale argomento a curve().

Se voglio fare questo nel modo più semplice, ho solo eseguito

curve(x^2,from=0,to=3) 

e funziona benissimo.

Supponiamo che io cerco di impostare una funzione wrapper (diciamo che ci sono altre cose che voglio fare all'interno della confezione, oltre a tracciare la curva):

f <- function(g) { 
    curve(g,from=0,to=3) 
} 

Questo funziona se mi passa una funzione:

f(function(x) x^2) 

fallisce se provo a passare x^2, quando R cerca di valutare l'espressione:

f(x^2) 
## Error in eval(expr, envir, enclos) (from #2) : object 'x' not found 

posso provare di prevenire questo utilizzando substitute all'interno della funzione:

f0 <- function(g) { 
    str(substitute(g)) 
    curve(substitute(g),from=0,to=3) 
} 
f0(x^2) 
## language x^2 
## Error in curve(substitute(g), from = 0, to = 3) (from #3) : 
## 'expr' must be a function, or a call or an expression containing 'x' 

OK, che suggerisce forse dovrei provare

f <- function(g) { 
    h <- as.expression(substitute(g)) 
    str(h) 
    curve(as.expression(substitute(g)),from=0,to=3) 
} 
f(x^2) 
## expression(x^2) 
## Error in curve(as.expression(substitute(g)), from = 0, to = 3) (from #4) : 
## 'expr' must be a function, or a call or an expression containing 'x' 

Per quel che vale,

  • questo fallisce in modo diverso con curve(h,...) ("funzione h non trovata")
  • fallisce nello stesso modo se as.call() è sostituito as.expression()
  • curve() non funziona su espressioni in ogni caso:

curve(expression(x^2),from=0,to=1) 
## Error in curve(expression(x^2), from = 0, to = 1) : 
## 'expr' did not evaluate to an object of length 'n' 

se provo debug curve() per vedere cosa sta succedendo, Abbiamo:

sexpr <- substitute(expr) 
... 
if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in% 
    all.vars(sexpr))) 
    stop(...) 

Qui sexpr è substitute(g), che non riesce il test xname %in% all.vars(sexpr) ...

Qualche idea su come gestirlo?

+1

Hai dato a "do.call" un colpo? Sembra che funzioni come con 'lm',' glm', ecc. –

risposta

6

Non volevo chiedere-e-poi-rispondi, ma ho capito la risposta (un?) Con un po 'di più in giro - mi è venuto in mente che non avevo ancora provato eval. eval(curve(substitute(g),from=0,to=3)) fa non lavoro, ma questo:

f1 <- function(g) { 
    eval(substitute(curve(g,from=0,to=3))) 
} 
f1(x^2) 

aggiornamento: @RichardScriven suggerisce che do.call() potrebbe funzionare anche - e lo fa!

f2 <- function(g) { 
    do.call(curve,list(substitute(g),from=0,to=3)) 
} 
f2(x^2) 

Ulteriori spiegazioni sono benvenute!

+2

sembra che questa funzionalità abbia sempre avuto lo scopo di funzionare in modo interattivo (di primo livello), quindi i workaround devono costruire esattamente la stessa chiamata Scrivere in modo interattivo, quindi valutare. – baptiste

+0

Beh, almeno non hai suggerito 'eval (parse (...))' tho 'sei arrivato pericolosamente vicino :-). Concordo con Richard S. che do.call è il tuo migliore amico in casi come questo. –

Problemi correlati