Ricerca…


introduzione

Gli operatori di pipe, disponibili in magrittr , dplyr e altri pacchetti R, elaborano un oggetto dati utilizzando una sequenza di operazioni passando il risultato di un passaggio come input per il passaggio successivo utilizzando gli operatori infissi anziché il metodo R più tipico di nidificato chiamate di funzione.

Si noti che lo scopo previsto degli operatori di pipe è aumentare la leggibilità umana del codice scritto. Vedere la sezione Note per considerazioni sulle prestazioni.

Sintassi

  • lhs%>% rhs # sintassi del pipe per rhs(lhs)

  • lhs%>% rhs (a = 1) # sintassi della pipe per rhs(lhs, a = 1)

  • lhs%>% rhs (a = 1, b =.) # sintassi della pipe per rhs(a = 1, b = lhs)

  • lhs% <>% rhs # sintassi del pipe per lhs <- rhs(lhs)

  • lhs% $% rhs (a) # sintassi pipe with(lhs, rhs(lhs$a))

  • lhs% T>% rhs # sintassi del pipe per { rhs(lhs); lhs }

Parametri

LHS RHS
Un valore o il segnaposto magrittr. Una chiamata di funzione usando la semantica magrittr

Osservazioni

Pacchetti che usano %>%

L'operatore di pipe è definito nel pacchetto magrittr , ma ha ottenuto enorme visibilità e popolarità con il pacchetto dplyr (che importa la definizione da magrittr ). Ora fa parte di tidyverse , che è una raccolta di pacchetti che "funzionano in armonia perché condividono rappresentazioni di dati comuni e design API" .

Il pacchetto magrittr fornisce inoltre diverse varianti dell'operatore del tubo per coloro che desiderano una maggiore flessibilità nelle tubazioni, come il tubo di assegnazione composto %<>% , il tubo di esposizione %$% e l'operatore tee %T>% . Fornisce anche una suite di funzioni alias per sostituire le funzioni comuni che hanno una sintassi speciale ( + , [ , [[ , ecc.) In modo che possano essere facilmente utilizzate all'interno di una catena di pipe.

Trovare documentazione

Come con qualsiasi operatore infisso (come + , * , ^ , & , %in% ), puoi trovare la documentazione ufficiale se la inserisci tra virgolette ?'%>%' O help('%>%') ( assumendo che tu abbia caricato un pacchetto che allega pkg:magrittr ).

Tasti di scelta rapida

C'è un hotkey speciale in RStudio per l'operatore di pipe: Ctrl+Shift+M ( Windows e Linux ), Cmd+Shift+M ( Mac ).

Considerazioni sulle prestazioni

Mentre l'operatore di tubazioni è utile, occorre tenere presente che l'impatto negativo sulla prestazione è dovuto principalmente al sovraccarico dell'utilizzo. Considerare le seguenti due cose attentamente quando si utilizza l'operatore di tubi:

  • Prestazioni della macchina (loop)
  • Valutazione ( object %>% rm() non rimuove l' object )

Uso di base e concatenamento

L'operatore di pipe, %>% , viene utilizzato per inserire un argomento in una funzione. Non è una funzione di base della lingua e può essere utilizzato solo dopo aver allegato un pacchetto che lo fornisce, come ad esempio magrittr . L'operatore del tubo prende il lato sinistro (LHS) del tubo e lo usa come primo argomento della funzione sul lato destro (RHS) del tubo. Per esempio:

library(magrittr)

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

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

La pipe può essere utilizzata per sostituire una sequenza di chiamate di funzione. Tubi multipli ci permettono di leggere e scrivere la sequenza da sinistra a destra, piuttosto che dall'interno verso l'esterno. Ad esempio, supponiamo di avere years definiti come fattore, ma vogliamo convertirlo in numerico. Per evitare possibili perdite di informazioni, prima convertiamo in carattere e poi in numerico:

years <- factor(2008:2012)

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

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

Se non vogliamo che LHS (Left Hand Side) sia usato come primo argomento sul RHS (lato destro), ci sono soluzioni alternative, come la denominazione degli argomenti o l'uso . per indicare dove va l'input inviato.

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

Sequenze funzionali

Data una sequenza di passaggi che utilizziamo ripetutamente, è spesso utile memorizzarla in una funzione. I pipe consentono di salvare tali funzioni in un formato leggibile avviando una sequenza con un punto come in:

. %>% RHS

Ad esempio, supponiamo di avere date dei fattori e di voler estrarre l'anno:

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

Possiamo esaminare la composizione della funzione digitandone il nome o utilizzando le functions :

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

Possiamo anche accedere a ciascuna funzione in base alla sua posizione nella sequenza:

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

In generale, questo approccio può essere utile quando la chiarezza è più importante della velocità.

Assegnazione con% <>%

Il pacchetto magrittr contiene un operatore infisso di assegnazione composta, %<>% , che aggiorna un valore prima di collegarlo a una o più espressioni rhs e quindi assegnare il risultato. Ciò elimina la necessità di digitare un nome oggetto due volte (una volta su ciascun lato dell'operatore di assegnazione <- ). %<>% deve essere il primo operatore infisso in una catena:

library(magrittr)
library(dplyr)

df <- mtcars

Invece di scrivere

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

o

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

L'operatore di assegnazione composto eseguirà il pipe e riassegnerà df :

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

Esposizione di contenuti con% $%

L'operatore del tubo di esposizione, %$% , espone i nomi delle colonne come simboli R all'interno dell'oggetto a sinistra nell'espressione a destra. Questo operatore è utile quando si collegano le funzioni che non hanno un argomento di data (diversamente da, ad esempio, lm ) e che non accettano nomi di dati e di colonne come argomenti (la maggior parte delle funzioni principali di dplyr).

L'operatore di pipe dell'esposizione %$% consente a un utente di evitare la rottura di una pipeline quando è necessario fare riferimento ai nomi di colonna. Ad esempio, supponiamo che desideri filtrare un data.frame e quindi eseguire un test di correlazione su due colonne 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

Qui la pipe %>% standard passa da data.frame a filter() , mentre la pipe %$% espone i nomi delle colonne a cor.test() .

La pipe dell'esposizione funziona come una versione in pipe della base R with() funzioni with() , e gli stessi oggetti di sinistra sono accettati come input.

Usando la pipa con dplyr e ggplot2

L'operatore %>% può anche essere usato per reindirizzare l'output di dplyr in ggplot. Ciò crea una pipeline di analisi dei dati esplorativi unificata (EDA) facilmente personalizzabile. Questo metodo è più veloce di fare le aggregazioni internamente in ggplot e ha il vantaggio aggiuntivo di evitare variabili intermedie non necessarie.

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

Creazione di effetti collaterali con% T>%

Alcune funzioni in R producono un effetto collaterale (ad es. Salvataggio, stampa, stampa, ecc.) E non sempre restituiscono un valore significativo o desiderato.

%T>% (operatore tee) consente di inoltrare un valore in una funzione di produzione di effetti collaterali mantenendo intatto il valore originale di lhs . In altre parole: l'operatore tee funziona come %>% , tranne che i valori restituiti sono lhs e non il risultato della funzione / espressione rhs .

Esempio: crea, convoglia, scrive e restituisce un oggetto. Se in questo esempio sono stati utilizzati %>% al posto di %T>% , la variabile all_letters conterrà NULL anziché il valore dell'oggetto ordinato.

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

Avvertenza: Piping di un oggetto senza nome per save() produrrà un oggetto denominato . quando caricato nell'area di lavoro con load() . Tuttavia, è possibile una soluzione alternativa utilizzando una funzione di supporto (che può anche essere scritta in linea come funzione anonima).

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow