Símbolos e operadores
Esse é um capítulo opcional. Leia se term algum interesse mais profundo em entender a linguagem R e Python.
Quem nunca viu código olha para df %>% filter(idade >= 18) |> mutate(faixa = idade %/% 10 * 10) e enxerga hieróglifo. Cada um daqueles símbolos tem nome, função e — em alguns casos — sutileza importante para a análise estar correta.
Este capítulo é um dicionário de consulta. A intenção não é decorar tudo, mas saber onde voltar quando você encontrar um símbolo desconhecido no código que está editando ou que o agente sugeriu.
Atribuição: <- e =
Em R, atribuição idiomática usa a seta para a esquerda:
idade_anos <- 45O = também funciona, mas é evitado fora de chamadas de função (mean(x = c(1, 2, 3))):
idade_anos = 45 # funciona, mas destoa do estilo tidyverseA seta vem de uma herança histórica. A linguagem S (precursora do R, criada nos Bell Labs nos anos 1970) herdou a notação da linguagem APL, que tinha uma tecla dedicada ← no teclado original (Ihaka; Gentleman, 1996). Quando S migrou para teclados ASCII, ← virou <-. R manteve a convenção.
Em Python, atribuição é sempre =:
idade_anos = 45Python tem ainda o operador walrus (morsa) :=, introduzido na versão 3.8 (2019) — atribui dentro de uma expressão:
if (n := len(dados)) > 100:
print(f"Dataset tem {n} linhas") # n foi definido na linha de cima= × ==
Um único = é atribuição (guarda valor). Dois == são comparação de igualdade (testa se dois valores são iguais).
x = 5 # ATRIBUI 5 a x
x == 5 # PERGUNTA: x é igual a 5? → TrueTrocar = por == (ou vice-versa) é o erro mais comum de iniciante e fonte de bugs silenciosos quando o código não dá erro mas faz a coisa errada.
Comparação
Iguais nas duas linguagens:
| Operador | O que testa | Exemplo |
|---|---|---|
== |
igualdade | idade == 18 |
!= |
diferente | grupo != "controle" |
<, > |
menor / maior | pressao > 140 |
<=, >= |
menor ou igual / maior ou igual | idade >= 18 |
Operadores lógicos
| O que faz | R (vetorizado) | R (escalar, dentro de if) |
Python |
|---|---|---|---|
| E | & |
&& |
and |
| OU | \| |
\|\| |
or |
| NÃO | ! |
! |
not |
A diferença em R entre & e && é sutil mas relevante:
# vetorizado: compara elemento a elemento
c(TRUE, FALSE, TRUE) & c(TRUE, TRUE, FALSE)
# → TRUE FALSE FALSE
# escalar: avalia o primeiro elemento, ideal dentro de if()
if (idade >= 18 && pressao < 140) { ... }A partir do R 4.3 (abril de 2023), && e || em valores não-escalares emitem aviso, reforçando a recomendação tidyverse de reservá-los para dentro de if.
Aritméticos: as armadilhas R × Python
Os aritméticos comuns (+, -, *, /) são iguais. O resto pega muito gente:
| Operação | R | Python | Atenção |
|---|---|---|---|
| Potência | 2 ^ 3 ou 2 ** 3 |
2 ** 3 |
^ em Python NÃO é potência — é XOR (ou exclusivo) bit a bit |
| Módulo (resto da divisão) | 7 %% 3 |
7 % 3 |
% em R é parte de operadores especiais (ex.: %>%), não módulo |
| Divisão inteira | 7 %/% 3 |
7 // 3 |
// em Python é divisão inteira; em outras linguagens, // é comentário (ver capítulo 03) |
Exemplo completo:
# R
2 ^ 3 # 8 — potência
7 %% 3 # 1 — resto da divisão
7 %/% 3 # 2 — quociente inteiro# Python
2 ** 3 # 8 — potência
7 % 3 # 1 — resto da divisão
7 // 3 # 2 — divisão inteiraO pipe: |> e %>% (só em R)
O pipe (encanador) passa o resultado de uma operação como primeiro argumento da próxima. É o que torna o estilo tidyverse legível:
# Sem pipe — leitura "de dentro para fora"
arrange(filter(mutate(dados, idade_dec = idade %/% 10), idade_dec >= 5), desc(idade))
# Com pipe — leitura linear, "passo a passo"
dados |>
mutate(idade_dec = idade %/% 10) |>
filter(idade_dec >= 5) |>
arrange(desc(idade))Existem duas versões do pipe em R:
|>— pipe nativo, embutido no R desde a versão 4.1 (maio de 2021). Não precisa de pacote.%>%— pipe do pacotemagrittr(Bache e Wickham, 2014), incluído automaticamente no tidyverse. Funciona desde versões antigas do R; oferece algumas funcionalidades extras (como o ponto.para indicar onde o argumento entra).
O tidyverse style guide (Wickham, 2024) recomenda preferir o |> nativo para projetos novos. Os dois funcionam intercambiavelmente em quase todos os casos.
- Positron / RStudio:
Ctrl + Shift + M(Windows/Linux) ouCmd + Shift + M(Mac) insere o pipe. Vá em Tools → Global Options → Code → Editing para escolher entre inserir|>ou%>%.
Em Python, não existe pipe nativo. Algumas bibliotecas (toolz, sspipe) oferecem sintaxe similar, mas raramente são usadas em ciência de dados. O equivalente idiomático em Python é encadear métodos:
# Python — equivalente ao pipe, via encadeamento de métodos
(dados
.assign(idade_dec=lambda d: d.idade // 10)
.query("idade_dec >= 5")
.sort_values("idade", ascending=False)
)Operadores específicos de R
| Símbolo | Nome / função | Exemplo |
|---|---|---|
~ |
fórmula (variável dependente ~ independentes) | lm(desfecho ~ idade + sexo, data = df) |
$ |
acessa coluna ou elemento nomeado | df$idade |
[ ] |
indexação por posição ou lógica | df[1, ] (primeira linha) |
[[ ]] |
extrai um único elemento de lista | lista[[1]] |
: |
sequência inclusiva | 1:5 → 1 2 3 4 5 |
? |
abre a página de ajuda | ?mean |
?? |
busca em todas as páginas de ajuda | ??regression |
<<- |
super-atribuição (escopo pai) | uso avançado, raro |
-> |
atribuição à direita (rara) | 45 -> idade |
Operadores específicos de Python
| Símbolo | Nome / função | Exemplo |
|---|---|---|
: |
sequência exclusiva + diversos usos | range(1, 5) → 1 2 3 4 (note: 5 fica de fora!) |
f"..." |
f-string, interpolação de variáveis | f"idade média: {media:.1f}" |
@ |
decorador | @staticmethod (avançado) |
** (em chamada) |
desempacota dicionário | funcao(**parametros) |
* (em chamada) |
desempacota lista | funcao(*argumentos) |
[ ] |
indexação | lista[0] (primeiro elemento — Python conta de zero!) |
. |
acessa atributo ou método | df.shape, texto.upper() |
- R:
1:5produz1 2 3 4 5(cinco elementos — inclui o último). - Python:
range(1, 5)produz1 2 3 4(quatro elementos — exclui o último). - Python:
lista[1:5]pega os elementos das posições 1, 2, 3, 4 (não a 5).
Mais uma diferença de “off-by-one” que gera bugs em quem alterna entre as duas linguagens.
Tabela de referência rápida (R × Python)
| O que | R | Python |
|---|---|---|
| Atribuição | <- |
= |
| Igualdade | == |
== |
| E lógico (vetor) | & |
(use np.logical_and ou pandas) |
| E lógico (escalar) | && |
and |
| Potência | ^ ou ** |
** |
| Módulo | %% |
% |
| Divisão inteira | %/% |
// |
| Pipe | \|> ou %>% |
(não existe nativo) |
| Sequência | 1:5 (1 a 5, inclusivo) |
range(1, 6) (exclusivo no fim) |
| Acesso a elemento | lista[[1]], df$col |
lista[0], df["col"] |
Conexão com IA
Símbolos densos é onde agentes de IA mais ajudam — você cola um trecho de código incompreensível no chat e pergunta “o que cada símbolo aqui faz?”. Funciona bem porque é texto compacto, com semântica bem definida; o modelo não precisa adivinhar contexto.
Vale dois cuidados:
- Confirme a versão do R/Python. Pipe nativo
|>só existe em R ≥ 4.1; walrus:=só em Python ≥ 3.8. Se o agente sugerir e seu ambiente for mais antigo, dá erro de sintaxe. - Não confunda
^em Python. Se o agente gerar código Python com^para potência, é alucinação clássica (confusão com R/MATLAB).^em Python é XOR bit a bit. Sempre revise antes de rodar em estatística.
O que vem a seguir
O próximo capítulo é sobre o “símbolo” mais traiçoeiro: o espaço em branco que define estrutura — em alguns lugares ele é decoração, em outros ele é sintaxe obrigatória. Indentação.