= 1:5
x <- 1:5
y
all.equal(x, y)
[1] TRUE
rm(x, y)
=
ou <-
?July 15, 2025
Há dois operadores para definir um objeto no R: =
e <-
. A maior parte dos usuários parece preferir o último apesar dele parecer um tanto inconveniente. Em teclados antigos, havia uma tecla específica com o símbolo <-
, mas em teclados ABNT modernos ele exige três teclas para ser escrito.
Para contornar este incômodo é comum criar um atalho no teclado para esse símbolo; o RStudio, por exemplo, tem um atalho usando a teclas Alt
e -
em conjunto.
Mas ainda assim fica a questão: por que não utilizar o =
? A resposta curta é que o símbolo <-
é a melhor e mais consistente forma de definir objetos R.
Na prática, contudo, há poucas diferenças entre as expressões e elas dificilmente vão fazer alguma diferença. Podemos começar com um exemplo bastante simples para entender estas diferenças.
O código abaixo cria duas variáveis, x
e y
, cujos valores são a sequência 1, 2, 3, 4, 5. Até aí tudo igual. A função all.equal
certifica que os objetos são iguais e a função rm
“deleta” os objetos. Esta última vai ser conveniente para manter os exemplos organizados.
Agora considere o código abaixo. A função median
está sendo aplicada em x <- 1:5
. O que acontece desta vez? O resultado é que é criada uma variável x
com valor 1 2 3 4 5
e também é impresso a mediana deste vetor, i.e., 3
.
Poderíamos fazer o mesmo usando =
, certo? Errado. Aí está uma das primeiras diferenças entre estes operadores. O código abaixo calcula a mediana do vetor, mas não cria um objeto chamado x
com valor 1 2 3 4 5
. Por quê? O problema é que o operador =
tem duas finalidades distintas. Ele serve tanto para definir novos objetos, como em x = 2
, como também para definir o valor dos argumentos de uma função, como em rnorm(n = 10, mean = 5, sd = 1)
. Coincidentemente, o nome do primeiro argumento da função median
é x. Logo, o código abaixo é interpretado como: tire a mediana do vetor 1 2 3 4 5
. O mesmo acontece com outras funções (ex: mean
, var
, etc.)
Outro exemplo em que há divergência entre os operadores é com o comando lm
. Usando <-
podemos escrever, numa única linha, um comando que define um objeto lm
(resultado de uma regressão) ao mesmo tempo em que pedimos ao R para imprimir os resultados desta regressão. O código abaixo faz justamente isto.
# Imprime os resultados da regressão e salva as info num objeto
# chamado 'fit'
summary(fit <- lm(mpg ~ wt, data = mtcars))
Call:
lm(formula = mpg ~ wt, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-4.543 -2.365 -0.125 1.410 6.873
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 37.285 1.878 19.86 < 0.0000000000000002 ***
wt -5.344 0.559 -9.56 0.00000000013 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.05 on 30 degrees of freedom
Multiple R-squared: 0.753, Adjusted R-squared: 0.745
F-statistic: 91.4 on 1 and 30 DF, p-value: 0.000000000129
[1] "lm"
Note que isto não é possível com o operador =
. Isto acontece, novamente, porque o =
é interpretado de maneira diferente quando aparece dentro de uma função. É necessário quebrar o código em duas linhas.
Error in summary.lm(fit = lm(mpg ~ wt, data = mtcars)): argument "object" is missing, with no default
Call:
lm(formula = mpg ~ wt, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-4.543 -2.365 -0.125 1.410 6.873
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 37.285 1.878 19.86 < 0.0000000000000002 ***
wt -5.344 0.559 -9.56 0.00000000013 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.05 on 30 degrees of freedom
Multiple R-squared: 0.753, Adjusted R-squared: 0.745
F-statistic: 91.4 on 1 and 30 DF, p-value: 0.000000000129
Há também algumas pequenas divergências pontuais. Os primeiros dois argumentos da função lm
são formula
e data
. Considere o código abaixo. Sem executar o código qual deve ser o resultado?
Estamos aplicando a função lm
em dois argumentos. O primeiro deles se chama formula
e é definido como mpg ~ wt
, o segundo é chamado data
e é definido como os valores no data.frame mtcars
. Ou seja, o resultado deve ser o mesmo do exemplo acima com median(x <- 1:5)
. A função é aplicada sobre os argumentos e os objetos formula
e data
são criados.
Call:
lm(formula = formula <- mpg ~ wt, data = data <- mtcars)
Coefficients:
(Intercept) wt
37.29 -5.34
mpg ~ wt
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Note que usei os nomes dos argumentos apenas para exemplificar o caso. Pode-se colocar um nome diferente, pois não estamos “chamando” o argumento e sim especificando qual valor/objeto a função deve utilizar.
Call:
lm(formula = a <- "mpg ~ wt", data = b <- mtcars)
Coefficients:
(Intercept) wt
37.29 -5.34
[1] "mpg ~ wt"
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
O mesmo não é possível com =
, por causa da duplicidade apontada acima.
Error in terms.formula(formula, data = data): argument is not a valid model
Há ainda mais alguns exemplos estranhos, resultados da ordem que o R processa os comandos. No R, é possível definir múltiplos objetos numa mesma linha da seguinte maneira
Agora considere os exemplos abaixo. O segundo código não funciona. Isto acontece porque o <-
tem “prioridade” e é lido primeiro.
De maneira geral, usar <-
é sempre melhor do que =
.
É difícil encontrar desvatagens em usar o <-
(além da dificuldade de escrevê-lo num teclado normal). Mas há pelo menos um caso em que ele pode levar a problemas. O código abaixo mostra como este operador pode ser sensível a espaços em branco. No caso, define-se o valor de x
como -2
. O primeiro teste verifica se o valor de x
é menor que -1. Logo, espera-se que o código imprima "ótimo"
pois -2
é menor que -1
. Já o segundo teste faz quase o mesmo. A única diferença é um espaço em branco, mas agora ao invés de um teste, a linha de código define o valor de x como 1
e imprime "ótimo"
, pois o valor do teste (por padrão) é TRUE
.
# Define x como -2
x <- -2
# Se x for menor que -1 (menos um) então "ótimo"
if (x < -1) "ótimo" else "errado"
[1] "ótimo"
[1] -2
[1] "ótimo"
[1] 1
Assim como muitos dos exemplos acima, é difícil imaginar que isto possa ser um problema real. Eventualmente, podemos apagar espaços em branco usando o ‘localizar e substituir’ e isto talvez leve a um erro similar.
Eu citei apenas dois operadores: =
e <-
; mas na verdade há ainda outros: <<-
, ->
e ->>
(veja help("assignOps")
). Os operadores com “flecha dupla” são comumente utilizadas dentro de funções para usos específicos.
É possível usar a flecha “ao contrário”, isto é, ->
como em 5 -> a
. Algumas pessoas acham que o operador ->
é mais intuitivo quando usado com “pipes”.
AirPassengers |>
log() |>
window(start = c(1955, 1), end = c(1958, 12)) -> sub_air_passengers
sub_air_passengers
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1955 5.489 5.451 5.587 5.595 5.598 5.753 5.897 5.849 5.743 5.613 5.468 5.628
1956 5.649 5.624 5.759 5.746 5.762 5.924 6.023 6.004 5.872 5.724 5.602 5.724
1957 5.753 5.707 5.875 5.852 5.872 6.045 6.142 6.146 6.001 5.849 5.720 5.817
1958 5.829 5.762 5.892 5.852 5.894 6.075 6.196 6.225 6.001 5.883 5.737 5.820
Além dos operadores base, o popular pacote magrittr
também possui um novo tipo de operador. Muitos conhecem o %>%
que ajuda a formar “pipes” e carregar objetos progressivamente em funções distintas. Menos conhecido, mas igualmente poderoso, o %<>%
faz algo parecido. Considere o exemplo abaixo.
Note que o código acima é equivalente ao abaixo.
A vantagem do operador %<>%
é de evitar a repetição do x <- x ...
o que pode ser conveniente quando o nome do objeto é longo. Da mesma forma, também pode ser aplicado para transformar elementos em uma lista ou colunas num data.frame
.
Apesar destas potenciais vantagens, não se recomenda o uso destes outros operadores. Por serem muito menos conhecidos, seu uso torna o código mais difícil de entender.
<-
é o mais corretoNo geral, o operador <-
é a forma mais “segura” de se definir objetos. De fato, atualmente, este operador é considerado o mais apropriado. O livro Advanced R, do influente autor Hadley Wickham, por exemplo, recomenda que se use o operador <-
exclusivamente para definir objetos.
A inconveniência de escrevê-lo num teclado moderno é contornada, como comentado acima, por atalhos como o Alt
+ -
no RStudio. Em editores de texto como o Positron, VSCode ou Sublime Text também é possível criar atalhos personalizados para o <-
. Por fim, o <-
fica bem bonito quando se usa uma fonte com ligaturas como o Fira Code.
O operador =
tem seu valor por ser mais intutivo, especialmente para usuários que já tem algum conhecimento de programação. Em projetos que envolvam outros colaboradores, o =
pode se provar o mais intuitivo.
É importante frisar que o <-
continua sendo o operador de predileção da comunidade dos usuários de R e novas funções/pacotes devem ser escritas com este sinal.
O ponto central deste post, na verdade, é mostrar como os operadores <-
e =
são muito similares na prática e que a escolha entre um ou outro acaba caindo numa questão subjetiva. Há quem acredite ser mais cômodo usar o =
não só porque ele é mais fácil de escrever, mas também porque ele é mais próximo de universal. Várias linguagens de programação comuns para a/o economista (Matlab, Python, Stata, etc.) usam o sinal de igualdade para definir objetos e parece estranho ter que usar o <-
somente para o R.
Em livros de econometria ambos os operadores são utilizados. Curiosamente, livros de econometria (microeconometria, econometria espacial) costumam usar o <-
. Livros como: Christoph Hanck, Martin Arnold, Alexander Gerber, and Martin Schmelzer * Hanck, Arnold, Gerber, Schmelzer. Introduction to Econometrics with R * Applied Econometrics with R * Arbia. Spatial Econometrics
Já livros de séries de tempo costumam usar o =
. Exemplos como:
Por sorte há opções bastante simples que trocam os =
para <-
corretamente como o formatR
apresentado abaixo. Veja também o addin do pacote styler
. Ou seja, é possível escrever seu código usando =
e trocá-los por <-
de maneira automática se for necessário.
x <- rnorm(n = 10, mean = 2)
Agora que você entende como definir objetos em R, o próximo passo é aprender sobre pipes - uma ferramenta fundamental que vai transformar a forma como você escreve código R.
|>
e magrittr %>%
Para aprofundar seus conhecimentos sobre objetos e atribuição em R: