# Exemplo usando o operador pipe nativo |>
resultado <- 1:10 |>
sum() |>
sqrt()
resultado[1] 7.416198
Em R, operadores pipe são usados para passar a saída de uma função para a entrada de outra, tornando o código mais legível e conciso. Este tutorial compara o operador pipe nativo |> introduzido no R 4.1.0 e o operador %>% do pacote magrittr.
|>O operador pipe nativo |> é uma nova adição ao R base. Ele permite escrever código mais limpo e legível ao encadear funções.
[1] 7.416198
Neste exemplo, a sequência de 1 a 10 é passada para a função sum(), e o resultado é então passado para a função `sqrt()```.
O mesmo resultado é obtido sem o operador pipe por:
O operador %>% do pacote `magrittr``` tem sido amplamente usado na comunidade R há vários anos. Ele serve ao mesmo propósito que o operador pipe nativo, mas possui alguns recursos adicionais.
[1] 7.416198
Este exemplo alcança o mesmo resultado que o anterior, mas usa o operador %>% do pacote magrittr.
Uma diferença chave é que %>% suporta placeholders (.), que podem ser úteis para pipelines mais complexos.
[1] 5.244044
O operador pipe nativo |> não suporta placeholders diretamente.
Usando o pipe nativo, a mesma expressão ficaria:
Portanto, torna-se necessário declarar uma função dentro da sequência se comandos.
O operador %>% do magrittr fornece mensagens de erro mais detalhadas e melhores capacidades de depuração. Se você encontrar um erro em um pipeline usando |>, a mensagem de erro pode ser menos informativa em comparação com o uso de %>%.
Ambos os operadores pipe têm desempenho semelhante na maioria dos casos. No entanto, |> por ser parte do R base, pode ter ligeiras vantagens de desempenho em alguns cenários devido à sua integração com a linguagem principal.
Tanto o operador pipe nativo |> quanto o operador %>% do magrittr são ferramentas poderosas para escrever código R limpo e legível. A escolha entre eles depende de suas necessidades específicas e preferências. Se você precisa de suporte a placeholders e depuração aprimorada, %>% é uma boa escolha. Para uma dependência mais leve e potencialmente melhor desempenho, |> é uma opção sólida. A seguir algumas sugestões para a escolha entre os operadores.
resultado <- dados |>
filter(variavel1 > 10) |>
mutate(nova_variavel = variavel2 * 2) |>
summarise(media = mean(nova_variavel))
# Sem o operador pipe, esta sequância de códigos poderia ficar:
res1 <- filter(dados, variável1 > 10)
res2 <- mutate(res1, nova_variavel = variavel2 * 2)
resultado <- summarise(res2, media = mean(nova_variavel))Consistência de Sintaxe: Utilize pipes para manter uma sintaxe consistente em todo o seu código, especialmente se você estiver trabalhando em um projeto colaborativo onde a consistência de estilo é importante.
Simplificação de Funções Aninhadas: Empregue operadores pipe para simplificar a leitura de funções aninhadas, evitando a necessidade de múltiplos parênteses.
Simplicidade Excessiva: Evite usar operadores pipe para operações extremamente simples onde o uso de pipes não adiciona clareza. Por exemplo, sum(1:10) é mais claro sem o pipe.
Depuração de Código: Não use pipes se você está tendo dificuldades para depurar uma sequência de operações. Em vez disso, atribua resultados intermediários a variáveis temporárias para inspecioná-los.
# Criando exemplos de data frames
dados1 <- data.frame(
categoria = rep(c("A", "B", "C"), each = 4),
variavel1 = rnorm(12, mean = 6, sd = 2)
)
dados2 <- data.frame(
categoria = rep(c("A", "B", "C"), each = 4),
variavel2 = rnorm(12, mean = 10, sd = 5)
)
library(dplyr)
# Operações complexas em uma única sequência de operadores pipe
resultado <- dados1 |>
group_by(categoria) |>
summarise(media_variavel1 = mean(variavel1)) |>
inner_join(
dados2 |>
group_by(categoria) |>
summarise(soma_variavel2 = sum(variavel2)),
by = "categoria"
) |>
mutate(nova_variavel = soma_variavel2 / media_variavel1) |>
arrange(desc(nova_variavel))
resultado# A tibble: 3 × 4
categoria media_variavel1 soma_variavel2 nova_variavel
<chr> <dbl> <dbl> <dbl>
1 C 6.15 51.7 8.41
2 B 6.38 39.8 6.24
3 A 5.87 27.0 4.60
O exemplo acima pode ser reescrito de forma que cada etapa tenha uma leitura mais clara.
# Passo 1: Filtrar e resumir dados1
resumo_dados1 <- dados1 |>
group_by(categoria) |>
summarise(media_variavel1 = mean(variavel1))
# Passo 2: Filtrar e resumir dados2
resumo_dados2 <- dados2 |>
group_by(categoria) |>
summarise(soma_variavel2 = sum(variavel2))
# Passo 3: Unir os resultados dos dois data frames
resultado_unido <- inner_join(resumo_dados1,
resumo_dados2,
by = "categoria") |>
mutate(nova_variavel = soma_variavel2 / media_variavel1) |>
arrange(desc(nova_variavel))
resultado_unido# A tibble: 3 × 4
categoria media_variavel1 soma_variavel2 nova_variavel
<chr> <dbl> <dbl> <dbl>
1 C 6.15 51.7 8.41
2 B 6.38 39.8 6.24
3 A 5.87 27.0 4.60
Embora o código tenha ficado mais longo, fica também mais simples de ser inspecionado.
Desempenho Crítico: Se você está preocupado com o desempenho crítico e a eficiência, pode ser melhor evitar pipes, já que eles podem adicionar alguma sobrecarga.
Ambiguidade de Funções: Evite pipes se o uso deles torna a ordem das operações ou a origem dos dados ambígua. Certifique-se de que a sequência de operações é clara e lógica.