Recherche…


Introduction

Les opérateurs de tuyauterie, disponibles dans magrittr , dplyr et autres packages R, traitent un objet de données en utilisant une séquence d'opérations en transmettant le résultat d'une étape comme étape de la prochaine étape à l'aide des opérateurs infixes plutôt que de la méthode R appels de fonction.

Notez que l'objectif des opérateurs de tuyauterie est d'accroître la lisibilité humaine du code écrit. Voir la section Remarques pour des considérations de performances.

Syntaxe

  • lhs%>% rhs # syntaxe de pipe pour rhs(lhs)

  • lhs%>% rhs (a = 1) # syntaxe de tuyau pour rhs(lhs, a = 1)

  • lhs%>% rhs (a = 1, b =.) # syntaxe de tuyau pour rhs(a = 1, b = lhs)

  • lhs% <>% rhs # syntaxe de tuyau pour lhs <- rhs(lhs)

  • lhs% $% rhs (a) # syntaxe de tuyau pour with(lhs, rhs(lhs$a))

  • lhs% T>% rhs # syntaxe de pipe pour { rhs(lhs); lhs }

Paramètres

lhs rhs
Une valeur ou l'espace réservé magrittr. Un appel de fonction utilisant la sémantique magrittr

Remarques

Packages utilisant %>%

L'opérateur de pipe est défini dans le package magrittr , mais il a gagné en visibilité et en popularité avec le package dplyr (qui importe la définition de magrittr ). Maintenant, il fait partie de tidyverse , une collection de paquets qui "fonctionnent en harmonie car ils partagent des représentations de données communes et la conception de l'API" .

Le package magrittr fournit également plusieurs variantes de l'opérateur de canalisation pour ceux qui souhaitent plus de flexibilité dans les canalisations, tels que le canal de magrittr composé %<>% , le canal d'exposition %$% et l'opérateur de départ %T>% . Il fournit également une suite de fonctions d'alias pour remplacer les fonctions communes qui ont une syntaxe spéciale ( + , [ , [[ , etc.) afin qu'elles puissent être facilement utilisées dans une chaîne de canaux.

Trouver la documentation

Comme avec n'importe quel opérateur infixe (tel que + , * , ^ , & , %in% ), vous pouvez trouver la documentation officielle si vous la mettez entre guillemets ?'%>%' Ou help('%>%') ( en supposant que vous avez chargé un paquet qui attache pkg:magrittr ).

Raccourcis clavier

Il y a un raccourci spécial dans RStudio pour l'opérateur du canal: Ctrl+Shift+M ( Windows & Linux ), Cmd+Shift+M ( Mac ).

Considérations de performance

Bien que l'opérateur de tuyauterie soit utile, sachez qu'il y a un impact négatif sur les performances, principalement en raison de son utilisation. Tenez compte des deux choses suivantes lorsque vous utilisez l'opérateur de canalisation:

  • Performances de la machine (boucles)
  • Evaluation ( object %>% rm() ne supprime pas d' object )

Utilisation de base et chaînage

L'opérateur de canal, %>% , permet d'insérer un argument dans une fonction. Ce n'est pas une fonctionnalité de base du langage et ne peut être utilisé qu'après avoir attaché un paquet qui le fournit, tel que magrittr . L'opérateur de conduite prend le côté gauche (LHS) du tuyau et l'utilise comme premier argument de la fonction sur le côté droit (RHS) du tuyau. Par exemple:

library(magrittr)

1:10 %>% mean
# [1] 5.5

# is equivalent to
mean(1:10)
# [1] 5.5

Le tube peut être utilisé pour remplacer une séquence d'appels de fonction. Plusieurs tuyaux nous permettent de lire et d'écrire la séquence de gauche à droite, plutôt que de l'intérieur vers l'extérieur. Par exemple, supposons que nous ayons des years définies comme facteur mais que nous souhaitons les convertir en données numériques. Pour éviter une éventuelle perte d’informations, nous convertissons d’abord en caractères puis en chiffres:

years <- factor(2008:2012)

# nesting
as.numeric(as.character(years))

# piping
years %>% as.character %>% as.numeric

Si nous ne voulons pas que le LHS (Left Hand Side) soit utilisé comme premier argument du RHS (Right Hand Side), il existe des solutions de contournement, telles que le nom des arguments ou l'utilisation . pour indiquer où va l’entrée canalisée.

# example with grepl
# its syntax:
# grepl(pattern, x, ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE)

# note that the `substring` result is the *2nd* argument of grepl
grepl("Wo", substring("Hello World", 7, 11))

# piping while naming other arguments
"Hello World" %>% substring(7, 11) %>% grepl(pattern = "Wo")

# piping with .
"Hello World" %>% substring(7, 11) %>% grepl("Wo", .)

# piping with . and curly braces
"Hello World" %>% substring(7, 11) %>% { c(paste('Hi', .)) }
#[1] "Hi World"

#using LHS multiple times in argument with curly braces and .
"Hello World" %>% substring(7, 11) %>% { c(paste(. ,'Hi', .)) }
#[1] "World Hi World"

Séquences fonctionnelles

Étant donné une séquence d'étapes que nous utilisons à plusieurs reprises, il est souvent utile de la stocker dans une fonction. Les tuyaux permettent de sauvegarder de telles fonctions dans un format lisible en commençant une séquence avec un point comme dans:

. %>% RHS

Par exemple, supposons que nous ayons des dates de facteurs et que nous voulons extraire l’année:

library(magrittr) # needed to include the pipe operators
library(lubridate)
read_year <- . %>% as.character %>% as.Date %>% year

# Creating a dataset
df <- data.frame(now = "2015-11-11", before = "2012-01-01")
#          now     before
# 1 2015-11-11 2012-01-01

# Example 1: applying `read_year` to a single character-vector
df$now %>% read_year
# [1] 2015

# Example 2: applying `read_year` to all columns of `df`
df %>% lapply(read_year) %>% as.data.frame  # implicit `lapply(df, read_year)
#    now before
# 1 2015   2012

# Example 3: same as above using `mutate_all`
library(dplyr)
df %>% mutate_all(funs(read_year))
# if an older version of dplyr use `mutate_each`
#    now before
# 1 2015   2012

Nous pouvons revoir la composition de la fonction en tapant son nom ou en utilisant des functions :

read_year
# Functional sequence with the following components:
# 
#  1. as.character(.)
#  2. as.Date(.)
#  3. year(.)
# 
# Use 'functions' to extract the individual functions. 

Nous pouvons également accéder à chaque fonction par sa position dans la séquence:

read_year[[2]]
# function (.) 
# as.Date(.)

En général, cette approche peut être utile lorsque la clarté est plus importante que la vitesse.

Affectation avec% <>%

Le paquet magrittr contient un opérateur d'infixe d'affectation composé, %<>% , qui met à jour une valeur en la redirigeant d'abord vers une ou plusieurs expressions rhs , puis en affectant le résultat. Cela élimine le besoin de saisir un nom d'objet deux fois (une fois de chaque côté de l'opérateur d'affectation <- ). %<>% doit être le premier opérateur infixe dans une chaîne:

library(magrittr)
library(dplyr)

df <- mtcars

Au lieu d'écrire

df <- df %>% select(1:3) %>% filter(mpg > 20, cyl == 6)

ou

df %>% select(1:3) %>% filter(mpg > 20, cyl == 6) -> df

L'opérateur d'affectation composé va à la fois canaliser et réaffecter df :

df %<>% select(1:3) %>% filter(mpg > 20, cyl == 6)

Exposer le contenu avec% $%

L'opérateur du canal d'exposition, %$% , expose les noms de colonne en tant que symboles R dans l'objet de gauche à l'expression du côté droit. Cet opérateur est pratique quand il passe dans des fonctions qui n'ont pas d'argument de data (contrairement à, disons, lm ) et qui ne prennent pas d'arguments data.frame et des noms de colonne (la plupart des fonctions principales de dplyr).

L'opérateur de canal d'exposition %$% permet à un utilisateur d'éviter de casser un pipeline lorsqu'il doit se référer aux noms de colonne. Par exemple, supposons que vous souhaitiez filtrer un fichier data.frame et exécuter un test de corrélation sur deux colonnes avec le cor.test :

library(magrittr)
library(dplyr)
mtcars %>%
  filter(wt > 2) %$%
  cor.test(hp, mpg)

#> 
#>  Pearson's product-moment correlation
#> 
#> data:  hp and mpg
#> t = -5.9546, df = 26, p-value = 2.768e-06
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  -0.8825498 -0.5393217
#> sample estimates:
#>        cor 
#> -0.7595673

Ici, le tube standard %>% passe le fichier data.frame à filter() , tandis que le tube %$% expose les noms de colonne à cor.test() .

Le tube d'exposition fonctionne comme une version canalisable des fonctions de base R with() , et les mêmes objets de gauche sont acceptés comme entrées.

Utiliser le tuyau avec dplyr et ggplot2

L'opérateur %>% peut également être utilisé pour diriger la sortie de dplyr vers ggplot. Cela crée un pipeline unifié d'analyse de données exploratoire (EDA) facilement personnalisable. Cette méthode est plus rapide que les agrégations internes à ggplot et présente l'avantage supplémentaire d'éviter les variables intermédiaires inutiles.

library(dplyr)
library(ggplot)


diamonds %>% 
    filter(depth > 60) %>% 
    group_by(cut) %>% 
    summarize(mean_price = mean(price)) %>% 
    ggplot(aes(x = cut, y = mean_price)) + 
        geom_bar(stat = "identity")

Créer des effets secondaires avec% T>%

Certaines fonctions de R produisent un effet secondaire (sauvegarde, impression, traçage, etc.) et ne renvoient pas toujours une valeur significative ou souhaitée.

%T>% (opérateur de départ) vous permet de transférer une valeur dans une fonction produisant des effets secondaires tout en conservant la valeur lhs origine. En d'autres termes: l'opérateur tee fonctionne comme %>% , sauf que les valeurs lhs sont lhs lui-même, et non le résultat de la fonction / expression rhs .

Exemple: Créer, diriger, écrire et renvoyer un objet. Si %>% était utilisé à la place de %T>% dans cet exemple, alors la variable all_letters contiendrait NULL plutôt que la valeur de l'objet trié.

all_letters <- c(letters, LETTERS) %>%
    sort %T>% 
    write.csv(file = "all_letters.csv")

read.csv("all_letters.csv") %>% head()
#   x
# 1 a
# 2 A
# 3 b
# 4 B
# 5 c
# 6 C

Attention: le fait de transférer un objet non nommé à save() produira un objet nommé . lorsqu'il est chargé dans l'espace de travail avec load() . Cependant, une solution de contournement utilisant une fonction d'assistance est possible (qui peut également être écrite en ligne en tant que fonction anonyme).

all_letters <- c(letters, LETTERS) %>%
    sort %T>% 
    save(file = "all_letters.RData")

load("all_letters.RData", e <- new.env())

get("all_letters", envir = e)
# Error in get("all_letters", envir = e) : object 'all_letters' not found

get(".", envir = e)
#  [1] "a" "A" "b" "B" "c" "C" "d" "D" "e" "E" "f" "F" "g" "G" "h" "H" "i" "I" "j" "J" 
# [21] "k" "K" "l" "L" "m" "M" "n" "N" "o" "O" "p" "P" "q" "Q" "r" "R" "s" "S" "t" "T" 
# [41] "u" "U" "v" "V" "w" "W" "x" "X" "y" "Y" "z" "Z"

# Work-around
save2 <- function(. = ., name, file = stop("'file' must be specified")) {
  assign(name, .)
  call_save <- call("save", ... = name, file = file)
  eval(call_save)
}

all_letters <- c(letters, LETTERS) %>%
    sort %T>%
    save2("all_letters", "all_letters.RData")


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow