Buscar..


Introducción

Los operadores de tuberías, disponibles en magrittr , dplyr y otros R, procesan un objeto de datos utilizando una secuencia de operaciones al pasar el resultado de un paso como entrada para el siguiente paso utilizando operadores de infijo en lugar del método R más típico de anidado función de llamadas.

Tenga en cuenta que el objetivo de los operadores de tuberías es aumentar la legibilidad humana del código escrito. Vea la sección de Comentarios para consideraciones de rendimiento.

Sintaxis

  • Sintaxis de rhs(lhs) lhs%>% rhs # para rhs(lhs)

  • lhs%>% rhs (a = 1) # sintaxis de tubería para rhs(lhs, a = 1)

  • lhs%>% rhs (a = 1, b =.) # sintaxis de tubería para rhs(a = 1, b = lhs)

  • lhs% <>% rhs # sintaxis de tuberías para lhs <- rhs(lhs)

  • lhs% $% rhs (a) # sintaxis de tubería para with(lhs, rhs(lhs$a))

  • lhs% T>% rhs # sintaxis de tubería para { rhs(lhs); lhs }

Parámetros

lhs rs
Un valor o el marcador de posición magrittr. Una llamada a la función utilizando la semántica magrittr.

Observaciones

Paquetes que utilizan %>%

El operador de tubería está definido en el paquete magrittr , pero ganó gran visibilidad y popularidad con el paquete dplyr (que importa la definición de magrittr ). Ahora es parte de tidyverse , que es una colección de paquetes que "funcionan en armonía porque comparten representaciones de datos comunes y diseño de API" .

El paquete magrittr también proporciona varias variaciones del operador de tubería para aquellos que desean una mayor flexibilidad en la tubería, como la tubería de asignación compuesta %<>% , la tubería de exposición %$% y el operador en %T>% . También proporciona un conjunto de funciones de alias para reemplazar funciones comunes que tienen una sintaxis especial ( + , [ , [[ , etc.) para que puedan usarse fácilmente dentro de una cadena de tuberías.

Encontrar documentación

Al igual que con cualquier operador de infijo (como + , * , ^ , & , %in% ), puede encontrar la documentación oficial si la pone entre comillas ?'%>%' O help('%>%') ( asumiendo que ha cargado un paquete que adjunta pkg:magrittr ).

Teclas de acceso rápido

Hay una tecla de acceso rápido especial en RStudio para el operador de tuberías: Ctrl+Shift+M ( Windows y Linux ), Cmd+Shift+M ( Mac ).

Consideraciones de rendimiento

Si bien el operador de tuberías es útil, tenga en cuenta que existe un impacto negativo en el rendimiento debido principalmente a la sobrecarga de su uso. Considere las siguientes dos cosas cuidadosamente al usar el operador de tubería:

  • Rendimiento de la máquina (bucles)
  • Evaluación ( object %>% rm() no elimina el object )

Uso básico y encadenamiento.

El operador de tubería, %>% , se usa para insertar un argumento en una función. No es una función básica del idioma y solo se puede usar después de adjuntar un paquete que lo proporcione, como magrittr . El operador de la tubería toma el lado izquierdo (LHS) del tubo y lo utiliza como primer argumento de la función en el lado derecho (RHS) del tubo. Por ejemplo:

library(magrittr)

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

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

La tubería se puede utilizar para reemplazar una secuencia de llamadas a funciones. Los múltiples tubos nos permiten leer y escribir la secuencia de izquierda a derecha, en lugar de hacerlo desde adentro hacia afuera. Por ejemplo, supongamos que tenemos years definidos como un factor, pero queremos convertirlo en un valor numérico. Para evitar una posible pérdida de información, primero convertimos a carácter y luego a numérico:

years <- factor(2008:2012)

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

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

Si no queremos que el LHS (lado izquierdo) se use como primer argumento en el RHS (lado derecho), hay soluciones alternativas, como nombrar los argumentos o usarlos . para indicar donde va la entrada entubada.

# 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"

Secuencias funcionales

Dada una secuencia de pasos que usamos repetidamente, a menudo es útil almacenarlo en una función. Las tuberías permiten guardar dichas funciones en un formato legible al iniciar una secuencia con un punto como en:

. %>% RHS

Como ejemplo, supongamos que tenemos fechas factoriales y queremos extraer el año:

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

Podemos revisar la composición de la función escribiendo su nombre o usando functions :

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

También podemos acceder a cada función por su posición en la secuencia:

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

En general, este enfoque puede ser útil cuando la claridad es más importante que la velocidad.

Asignación con% <>%

El paquete magrittr contiene un operador de asignación de infijo compuesto, %<>% , que actualiza un valor insertándolo primero en una o más expresiones de rhs y luego asignando el resultado. Esto elimina la necesidad de escribir el nombre de un objeto dos veces (una vez en cada lado del operador de asignación <- ). %<>% debe ser el primer operador de infijo en una cadena:

library(magrittr)
library(dplyr)

df <- mtcars

En lugar de escribir

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

o

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

El operador de asignación compuesta canalizará y reasignará df :

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

Exponer contenidos con% $%

El operador del tubo de exposición, %$% , expone los nombres de las columnas como símbolos R dentro del objeto del lado izquierdo a la expresión del lado derecho. Este operador es útil cuando canaliza funciones que no tienen un argumento de data (a diferencia de, digamos, lm ) y que no toman un data.frame y nombres de columna como argumentos (la mayoría de las funciones principales de dplyr).

El operador de tubería de exposición %$% permite que un usuario evite romper una tubería cuando necesite referirse a nombres de columnas. Por ejemplo, supongamos que desea filtrar un data.frame y luego ejecutar una prueba de correlación en dos columnas con 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

Aquí el %>% pipe estándar pasa el data.frame a través de filter() , mientras que el cor.test() %$% expone los nombres de columna a cor.test() .

El tubo de exposición funciona como una versión de la base R with() funciones with() capaz de canalizar, y los mismos objetos del lado izquierdo se aceptan como entradas.

Usando el tubo con dplyr y ggplot2

El operador %>% también se puede usar para canalizar la salida de dplyr en ggplot. Esto crea un flujo de análisis de datos exploratorios (EDA) unificado que es fácilmente personalizable. Este método es más rápido que hacer las agregaciones internamente en ggplot y tiene el beneficio adicional de evitar variables intermedias innecesarias.

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")

Creando efectos secundarios con% T>%

Algunas funciones en R producen un efecto secundario (es decir, guardar, imprimir, trazar, etc.) y no siempre devuelven un valor significativo o deseado.

%T>% (operador de tee) le permite reenviar un valor a una función que produce efectos secundarios mientras mantiene intacto el valor original de lhs . En otras palabras: el operador de tee funciona como %>% , excepto que los valores de retorno son lhs sí, y no el resultado de la función / expresión de rhs .

Ejemplo: crear, canalizar, escribir y devolver un objeto. Si se utilizara %>% en lugar de %T>% en este ejemplo, entonces la variable all_letters contendrá NULL lugar del valor del objeto ordenado.

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

Advertencia: la canalización de un objeto sin nombre a save() producirá un objeto denominado . cuando se carga en el espacio de trabajo con load() . Sin embargo, es posible una solución alternativa utilizando una función auxiliar (que también se puede escribir en línea como una función anónima).

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow