2009-11-16 8 views
488

Quali sono le differenze tra gli operatori di assegnazione = e <- in R?Quali sono le differenze tra "=" e "<-" in R?

So che gli operatori sono leggermente diverse, come mostra questo esempio

x <- y <- 5 
x = y = 5 
x = y <- 5 
x <- y = 5 
# Error in (x <- y) = 5 : could not find function "<-<-" 

Ma è questa l'unica differenza?

+22

Come indicato [qui] (http://blog.revolutionanalytics.com/2008/12/use-equals-or-arrow-for-assignment.html) le origini del '<-' il simbolo proviene dalle vecchie tastiere APL che in realtà avevano una sola chiave '<-' su di esse. – joran

risposta

481

La differenza in assignment operators è più chiara quando li si utilizza per impostare un valore argomento in una chiamata di funzione. Ad esempio:

median(x = 1:10) 
x 
## Error: object 'x' not found 

In questo caso, x viene dichiarata nell'ambito della funzione, quindi non esiste nell'area di lavoro dell'utente.

median(x <- 1:10) 
x  
## [1] 1 2 3 4 5 6 7 8 9 10 

In questo caso, x viene dichiarata nello spazio di lavoro dell'utente, in modo da poter utilizzare dopo la chiamata di funzione è stata completata.


C'è una preferenza generale tra la comunità R per l'utilizzo di <- per l'assegnazione (se non in funzione di firme) per la compatibilità con (molto) le vecchie versioni di S-Plus. Si noti che gli spazi contribuiscono a chiarire situazioni come

x<-3 
# Does this mean assignment? 
x <- 3 
# Or less than? 
x < -3 

maggior R IDE hanno scorciatoie da tastiera per rendere <- più facile da digitare. Ctrl += in Architect, Alt +- in RStudio (Opzione + - sotto MacOS), Maiusc +- (sottolineatura) in emacs + ESS.


Se preferite scrivendo = a <- ma si desidera utilizzare il simbolo di assegnazione più comune per il codice rilasciato pubblicamente (il CRAN, per esempio), allora si può utilizzare una delle tidy_* funzioni nel pacchetto formatR automaticamente sostituire = con <-.

library(formatR) 
tidy_source(text = "x=1:5", arrow = TRUE) 
## x <- 1:5 

La risposta alla domanda "Perché x <- y = 5 genera un errore, ma non x <- y <- 5?" è "È la magia contenuta nel parser". La sintassi di R contiene many ambiguous cases che devono essere risolti in un modo o nell'altro.Il parser sceglie di risolvere i bit dell'espressione in ordini diversi a seconda che sia stato utilizzato = o <-.

Per capire cosa sta succedendo, è necessario sapere che l'assegnazione restituisce silenziosamente il valore assegnato. Lo si può vedere più chiaramente stampando esplicitamente, ad esempio print(x <- 2 + 3).

In secondo luogo, è più chiaro se si utilizza la notazione del prefisso per l'assegnazione. Così

x <- 5 
`<-`(x, 5) #same thing 

y = 5 
`=`(y, 5) #also the same thing 

Il parser interpreta x <- y <- 5 come

`<-`(x, `<-`(y, 5)) 

ci si potrebbe aspettare che x <- y = 5 sarebbe allora

`<-`(x, `=`(y, 5)) 

ma in realtà si arriva interpretato come

`=`(`<-`(x, y), 5) 

Questo perché = ha precedenza inferiore rispetto a <-, come mostrato nella pagina di guida ?Syntax.

+1

Questo è anche menzionato nel capitolo 8.2.26 di [The R Inferno] (http://www.burns-stat.com/pages/Tutor/R_inferno.pdf) di Patrick Burns (Non sono io che una raccomandazione comunque) – Uwe

+1

Tuttavia, 'median ((x = 1:10))' ha lo stesso effetto di 'median (x <- 1:10) '. –

19

Gli operatori <- e = assegnano all'ambiente in cui vengono valutati. L'operatore <- può essere utilizzato ovunque, mentre l'operatore = è consentito solo al livello superiore (per esempio, nella espressione completa digitato al richiamo di ordine) o come una delle sottoespressioni in un elenco di espressioni rinforzato.

+8

Penso che "livello superiore" significhi a livello di istruzione, piuttosto che a livello di espressione. Quindi 'x <- 42' da solo è una dichiarazione; in 'if (x <- 42) {}' sarebbe un'espressione e non è valido. Per essere chiari, questo non ha nulla a che fare con se si è nell'ambiente globale o no. –

+0

Questo: "l'operatore = è consentito solo al livello superiore" è un fraintendimento ampiamente diffuso e completamente sbagliato. –

+0

Questo non è vero - per esempio, questo funziona, anche se l'assegnazione non è un'espressione completa: '1 + (x = 2)' –

81

La guida di stile R di Google semplifica il problema vietando "=" per l'assegnazione. Non è una cattiva scelta.

https://google.github.io/styleguide/Rguide.xml

Il manuale R va in bel dettaglio su tutti i 5 operatori di assegnazione.

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html

+96

Lo svantaggio dell'assegnazione accidentale di 'x <-y' quando' x <-y' era inteso, mi fa arrabbiare così tanto che personalmente preferisco '='. Avere il tuo codice dipende dal fatto che lo spazio bianco sia presente non mi sembra buono. È giusto suggerire la spaziatura come consiglio di stile, ma affinché il tuo codice funzioni in modo diverso se uno spazio è presente o no? Cosa succede se riformattate il vostro codice, o usate la ricerca e la sostituzione, lo spazio bianco a volte può scomparire e il codice va storto. Questo non è un problema con '='. IIUC, proibendo '=' equivale a richiedere "' <- '"; vale a dire, 3 caratteri incluso uno spazio, non solo "' <-' ". –

+9

Si noti che qualsiasi non-0 è considerato "VERO" di R. Quindi se si intende verificare se 'x' è minore di' -y', si potrebbe scrivere 'if (x <-y)' che non avviserà o errore, e sembra funzionare bene. Sarà 'FALSE' solo quando' y = 0', comunque. –

+2

Se si proibisce '=' e si usa '<-', allora è difficile arguire che un passo extra di 'grep '[^ <] <- [^]" * .R' non è necessario. '=' non ha bisogno di un simile 'grep'. –

27

Secondo John Chambers, l'operatore = è consentito solo al "livello superiore", il che significa che non è ammesso nel strutture di controllo come if, rendendo il seguente errore di programmazione illegale.

> if(x = 0) 1 else x 
Error: syntax error 

Come scrive "Impedire la nuova forma assegnazione [=] nelle espressioni di controllo evita errori di programmazione (come nell'esempio precedente) che sono più probabilmente con l'operatore uguale rispetto ad altri compiti S".

È possibile eseguire questa operazione se è "isolato dalla struttura logica circostante, da parentesi graffe o da una coppia aggiuntiva di parentesi", quindi if ((x = 0)) 1 else x funzionerebbe.

Vedi http://developer.r-project.org/equalAssign.html

+0

Cosa ti aspetti che quella linea faccia? Sicuramente, è equivalente a 'x = 0'? –

+11

È un errore comune, "x == 0" è quasi sempre inteso invece. – Aaron

+12

Ah, sì, ho trascurato che hai detto "errore di programmazione". In realtà è una buona notizia che ciò provochi un errore. E una buona ragione per preferire 'x = 0' come compito su' x <-0'! –

23

x = y = 5 è equivalente a x = (y = 5), perché gli operatori di assegnazione "gruppo" da destra a sinistra, che funziona. Significato: assegnare 5 a y, lasciando il numero 5; e quindi assegnare quel 5 a x.

Questo non è lo stesso di (x = y) = 5, che non funziona! Significato: assegnare il valore di y a x, lasciando il valore di y; e quindi assegnare 5 a, umm ..., che cosa esattamente?

Quando si miscelano i diversi tipi di operatori di assegnazione, <- si lega più stretto di =. Quindi x = y <- 5 viene interpretato come x = (y <- 5), che è il caso che ha senso.

Sfortunatamente, x <- y = 5 viene interpretato come (x <- y) = 5, che è il caso che non funziona!

Vedere ?Syntax e ?assignOps per la precedenza (vincolante) e le regole di raggruppamento.

4

Questo può anche aggiungere alla comprensione della differenza tra questi due operatori:

df <- data.frame(
     a = rnorm(10), 
     b <- rnorm(10) 
) 

Per il primo elemento R ha assegnato valori e nome proprio, mentre il nome del secondo elemento sembra un po 'strano.

str(df) 
# 'data.frame': 10 obs. of 2 variables: 
# $ a    : num 0.6393 1.125 -1.2514 0.0729 -1.3292 ... 
# $ b....rnorm.10.: num 0.2485 0.0391 -1.6532 -0.3366 1.1951 ... 

R versione 3.3.2 (2016-10-31); macOS Sierra 10.12.1

+4

puoi dare una spiegazione più dettagliata del perché questo accade/cosa sta succedendo qui? (suggerimento: 'data.frame' prova ad usare il nome della variabile fornita come nome dell'elemento nel frame dati) –

+0

Pensavo che potesse essere un bug? E se sì, come e dove lo denuncio? –

+1

non è un bug. Ho cercato di suggerire la risposta nel mio commento sopra. Quando si imposta il nome dell'elemento, R utilizzerà l'equivalente di 'make.names (" b <- rnorm (10) ")'. –