R Language                
            Операторы труб (%>% и другие)
        
        
            
    Поиск…
Вступление
 Операторы труб, доступные в magrittr , dplyr и других R-пакетах, обрабатывают объект данных, используя последовательность операций, передавая результат одного шага в качестве ввода для следующего шага с использованием инфикс-операторов, а не более типичный R-метод вложенных вызовы функций. 
Обратите внимание, что целью операторов труб является повышение удобочитаемости письменного кода. См. Раздел «Примечания» для соображений производительности.
Синтаксис
- lhs%>% rhs # pipe синтаксис для - rhs(lhs)
- lhs%>% rhs (a = 1) # синтаксис канала для - rhs(lhs, a = 1)
- lhs%>% rhs (a = 1, b =.) # синтаксис канала для - rhs(a = 1, b = lhs)
- lhs% <>% rhs # pipe синтаксис для - lhs <- rhs(lhs)
- lhs% $% rhs (a) # синтаксис канала для - with(lhs, rhs(lhs$a))
- lhs% T>% rhs # синтаксис канала для - { rhs(lhs); lhs }
параметры
| л.ш. | шк | 
|---|---|
| Значение или заполнитель magrittr. | Вызов функции с использованием семантики magrittr | 
замечания
 Пакеты, которые используют %>% 
 Оператор трубы определен в пакете magrittr , но он приобрел огромную видимость и популярность в пакете dplyr (который импортирует определение из magrittr ). Теперь это часть tidyverse , которая представляет собой набор пакетов, которые «работают в гармонии, потому что они имеют общие представления данных и дизайн API» . 
 Пакет magrittr также предоставляет несколько вариантов оператора труб для тех, кто хочет больше гибкости в трубопроводах, например, составной соединительный трубопровод %<>% , трубопровод экспозиции %$% и оператор тройника %T>% . Он также предоставляет набор функций псевдонимов для замены общих функций, которые имеют специальный синтаксис ( + , [ , [[ и т. Д.]), Чтобы их можно было легко использовать в цепочке труб. 
Поиск документации
 Как и в любом инфиксном операторе (например, + , * , ^ , & , %in% ), вы можете найти официальную документацию, если вы поместите ее в кавычки: ?'%>%' Или help('%>%') ( если вы загрузили пакет, который прикрепляет pkg:magrittr ). 
Клавиатурный
 В RStudio для оператора трубы есть специальная горячая клавиша: Ctrl+Shift+M ( Windows и Linux ), Cmd+Shift+M ( Mac ). 
Рекомендации по производительности
В то время как оператор трубы полезен, имейте в виду, что это негативно сказывается на производительности, в основном из-за накладных расходов на его использование. При использовании оператора трубы внимательно рассмотрите следующие две вещи:
- Производительность станка (петли)
-  Оценка ( object %>% rm()не удаляетobject)
Основное использование и цепочки
 Оператор трубы, %>% , используется для вставки аргумента в функцию. Он не является базовым признаком языка и может использоваться только после присоединения пакета, который его предоставляет, например, magrittr . Оператор трубы берет левую сторону (LHS) трубы и использует ее в качестве первого аргумента функции справа (RHS) трубы. Например: 
library(magrittr)
1:10 %>% mean
# [1] 5.5
# is equivalent to
mean(1:10)
# [1] 5.5
 Труба может использоваться для замены последовательности вызовов функций. Несколько труб позволяют нам читать и записывать последовательность слева направо, а не изнутри наружу. Например, предположим, что мы определили years как фактор, но хотим преобразовать его в числовой. Чтобы предотвратить возможную потерю информации, мы сначала конвертируем в символ, а затем в числовой: 
years <- factor(2008:2012)
# nesting
as.numeric(as.character(years))
# piping
years %>% as.character %>% as.numeric
 Если мы не хотим, чтобы LHS (Left Hand Side) использовался в качестве первого аргумента в RHS (Right Hand Side), есть временные решения, такие как именование аргументов или использование . для указания того, куда поступает входной канал. 
# 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"
Функциональные последовательности
Учитывая последовательность шагов, которые мы используем многократно, часто бывает удобно хранить ее в функции. Трубы позволяют сохранить такие функции в читаемом формате, запустив последовательность с точкой, как в:
. %>% RHS
В качестве примера предположим, что у нас есть даты факторов и хотим извлечь год:
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
 Мы можем просмотреть состав функции, набрав ее имя или используя functions : 
read_year
# Functional sequence with the following components:
# 
#  1. as.character(.)
#  2. as.Date(.)
#  3. year(.)
# 
# Use 'functions' to extract the individual functions. 
Мы также можем получить доступ к каждой функции по ее положению в последовательности:
read_year[[2]]
# function (.) 
# as.Date(.)
Как правило, такой подход может быть полезен, когда ясность важнее скорости.
Присвоение% <>%
 Пакет magrittr содержит инфикс-оператор составного назначения, %<>% , который обновляет значение, сначала передавая его в одно или несколько выражений rhs а затем назначая результат. Это устраняет необходимость дважды вводить имя объекта (один раз с каждой стороны оператора присваивания <- ). %<>% должен быть первым инфикс-оператором в цепочке: 
library(magrittr)
library(dplyr)
df <- mtcars
Вместо написания
df <- df %>% select(1:3) %>% filter(mpg > 20, cyl == 6)
или же
df %>% select(1:3) %>% filter(mpg > 20, cyl == 6) -> df
 Совокупный оператор присваивания будет как передавать, так и переназначать df : 
df %<>% select(1:3) %>% filter(mpg > 20, cyl == 6)
Предоставление содержимого с% $%
 Оператор трубы изложения, %$% , выдает имена столбцов в виде символов R в левом боковом объекте в выражение правой части. Этот оператор удобен при подключении к функциям, у которых нет аргумента data (в отличие, скажем, lm ), и которые не принимают имена data.frame и столбцов в качестве аргументов (большинство основных функций dplyr). 
 Оператор трубы изложения %$% позволяет пользователю избежать разрыва конвейера при необходимости ссылаться на имена столбцов. Например, предположим, что вы хотите отфильтровать файл data.frame, а затем запустить корреляционный тест на двух столбцах с 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
 Здесь стандартный %>% pipe передает файл data.frame через filter() , в то время как %$% pipe предоставляет имена столбцов cor.test() . 
 Труба экспозиции работает как труба, пригодная для работы с базовыми функциями R with() , и в качестве входных сигналов принимаются одни и те же объекты левой стороны. 
Использование трубы с dplyr и ggplot2
 Оператор %>% также может использоваться для вывода вывода dplyr в ggplot. Это создает единый исследовательский анализ данных (EDA), который легко настраивается. Этот метод быстрее, чем выполнение агрегирования внутри ggplot, и имеет дополнительное преимущество в предотвращении ненужных промежуточных переменных. 
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")
Создание побочных эффектов при% T>%
Некоторые функции в R создают побочный эффект (например, сохранение, печать, печать и т. Д.) И не всегда возвращают значимое или желаемое значение.
 %T>% (тройник оператор) позволяет пересылать значение в побочном эффекте продуцирующих функцию, сохраняя при этом оригинальном lhs значения нетронутым. Другими словами: оператор tee работает как %>% , за исключением того, что возвращаемые значения являются lhs , а не результатом функции / выражения rhs . 
 Пример. Создайте, создайте канал, напишите и верните объект. Если %>% были использованы вместо %T>% в этом примере, то переменная all_letters будет содержать NULL , а не значение отсортированного объекта. 
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
 Предупреждение: при вызове неназванного объекта для save() будет создан объект с именем . при загрузке в рабочую область с load() . Однако возможно обходное решение с использованием вспомогательной функции (которая также может быть написана встроенной как анонимная функция). 
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")