2014-12-03 15 views
6

Ho qualche codice R:Come funziona il tempo di sistema di R?

time.read = system.time(df <- data.frame(fread(f))) 
print(class(time.read)) 
#[1] "proc_time" 
print(class(df)) 
#[1] "data.frame" 

qualche modo quando questo viene eseguito, nella principale R ambiente/portata:

  • time.read ha un valore esiste
  • df e contiene il corretto data.frame

Ho pensato che le variabili create all'interno di una funzione non fossero disponibili al di fuori dell'ambito della funzione? Come funziona? E perché dopo aver eseguito quanto segue non esiste nell'ambiente R principale?

fx <- function(z){return(1)} 
out = fx(y <- 300) 
print(out) 
#[1] 1 
print(y) 
#Error in print(y) : object 'y' not found 

Grazie!

risposta

18

Ottima domanda! R fa qualcosa di particolare con la sua argomentazione, che causa molto confusione nella ma è anche molto utile.

Quando si passa un argomento in una funzione in R, non viene valutato fino a in realtà è utilizzato all'interno della funzione. Prima di questo, l'argomento si trova appena in un contenitore speciale chiamato promise. Le promesse contengono un'espressione e l'ambiente in cui devono essere valutate - per gli argomenti , che è l'ambiente del chiamante.

Ma non appena si utilizza l'argomento all'interno della funzione, il suo valore è calcolato. Questo è il modo in cui funziona system.time. Semplificata:

system.time = function (expr) { 
    before = proc.time() 
    expr 
    proc.time() - before 
} 

In altre parole, la funzione semplicemente registra l'ora prima di guardare il suo argomento . Quindi esamina il suo argomento e quindi ne determina la valutazione, e quindi registra il tempo trascorso. Ricorda però che la valutazione dell'argomento avviene nell'ambito del chiamante, quindi nel tuo caso la destinazione del compito (df) è anche visibile nell'ambito genitore.

Nel secondo esempio, la funzione fx non esamina mai il suo argomento, pertanto non viene mai valutata . Si può facilmente cambiare la situazione, costringendo la valutazione della sua tesi , semplicemente utilizzando esso:

fx <- function(z) { 
    z 
    return(1) 
} 

Infatti, R ha una funzione speciale - force per questo scopo:

fx <- function(z) { 
    force(z) 
    return(1) 
} 

Ma force è semplicemente zucchero sintattico, e la sua definizione è semplicemente di tornare suo argomento:

force = function (x) x 

Il fatto che R non valuta i suoi argomenti immediati è utile perché è possibile recuperare il modulo non valutato all'interno della funzione anche con .Questo è noto come non-standard evaluation, ed è talvolta utilizzato per valutare l' espressione in una diversa portata(utilizzando la funzione eval con argomento envir specificato), o per recuperare informazioni sul non valutata, espressione.

Molte funzioni utilizzano questo, il più prominente plot, che indovina predefinita etichette degli assi in base ai tracciati variabili/espressioni:

x = seq(0, 2 * pi, length.out = 100) 
plot(x, sin(x)) 

Ora le etichette degli assi sono x e sin(x). La funzione plot sa perché al suo interno, si può guardare le espressioni non valutate dei suoi argomenti delle funzioni:

xlabel = deparse(substitute(x)) 
ylabel = deparse(substitute(y)) 

substitute recupera l'espressione non valutata. deparse lo converte in una rappresentazione di stringa.

+1

Buona risposta, tranne che 'system.time' in realtà non usa' eval' (almeno non nella mia versione di R). Valuta direttamente l'espressione di promessa, senza nemmeno usare 'force', come nella tua seconda versione di' fx'. – mrip

+0

@mrip Sì, ho una mezza intenzione di riscrivere la mia risposta, perché la mia semplificazione lo rende * più * complicato. In R, l'argomento * ogni * funzione è una promessa, e la valutazione non standard è semplicemente un caso speciale di ciò in cui l'utente non ha valutato l'argomento della funzione (immediatamente), ma invece lo ha sostituito. –

+0

@mrip Scratch che, sono andato avanti e ho completamente riscritto la risposta. Cosa ne pensi? È più corretto ora, ma è ancora comprensibile? –

Problemi correlati