Sök…


Introduktion

Röroperatörer, tillgängliga i magrittr , dplyr och andra R-paket, bearbetar ett dataobjekt med hjälp av en sekvens av operationer genom att lämna resultatet av ett steg som ingång för nästa steg med infix-operatörer snarare än den mer typiska R-metoden för att kapsla funktion samtal.

Observera att det avsedda syftet med röroperatörer är att öka den mänskliga läsbarheten för skriftlig kod. Se avsnittet Kommentarer för resultathänsyn.

Syntax

  • lhs%>% rhs # rörsyntax för rhs(lhs)

  • lhs%>% rhs (a = 1) # rörsyntax för rhs(lhs, a = 1)

  • lhs%>% rhs (a = 1, b =.) # rörsyntax för rhs(a = 1, b = lhs)

  • lhs% <>% rhs # lhs <- rhs(lhs) för lhs <- rhs(lhs)

  • lhs% $% rhs (a) # rörsyntax för with(lhs, rhs(lhs$a))

  • lhs% T>% rhs # rörsyntax för { rhs(lhs); lhs }

parametrar

lhs rhs
Ett värde eller den magrittr platshållaren. Ett funktionssamtal med magrittr semantik

Anmärkningar

Paket som använder %>%

magrittr definieras i magrittr paketet, men den fick stor synlighet och popularitet med dplyr paketet (som importerar definitionen från magrittr ). Nu är det en del av tidyverse , som är en samling paket som "fungerar i harmoni eftersom de delar gemensamma datarepresentationer och API-design" .

magrittr paketet tillhandahåller också flera varianter av röroperatören för dem som vill ha mer flexibilitet i rörledningar, såsom sammansatt tilldelningsrör %<>% , exponeringsröret %$% och teeoperatören %T>% . Den tillhandahåller också en serie aliasfunktioner för att ersätta vanliga funktioner som har speciell syntax ( + , [ , [[ , etc.) så att de enkelt kan användas i en rörkedja.

Hitta dokumentation

Som med alla infixoperatörer (som + , * , ^ , & , %in% ), kan du hitta den officiella dokumentationen om du lägger den i offert ?'%>%' Eller help('%>%') ( förutsatt att du har laddat ett paket som bifogar pkg:magrittr ).

Snabbtangenter

Det finns en speciell snabbtangent i RStudio för röroperatören : Ctrl+Shift+M ( Windows & Linux ), Cmd+Shift+M ( Mac ).

Resultathänsyn

Medan röroperatören är användbar, ska du vara medveten om att det har en negativ inverkan på prestanda beroende främst på omkostnaderna för att använda den. Tänk på följande två saker noggrant när du använder röroperatören:

  • Maskinprestanda (slingor)
  • Utvärdering ( object %>% rm() tar inte bort object )

Grundläggande användning och kedja

Röroperatören, %>% , används för att infoga ett argument i en funktion. Det är inte en basfunktion i språket och kan bara användas efter att ha anslutit ett paket som tillhandahåller det, till exempel magrittr . Röroperatören tar vänster sida (LHS) på röret och använder det som det första argumentet för funktionen på höger sida (RHS) för röret. Till exempel:

library(magrittr)

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

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

Röret kan användas för att ersätta en sekvens av funktionssamtal. Flera rör tillåter oss att läsa och skriva sekvensen från vänster till höger, snarare än inifrån och ut. Anta till exempel att vi har years definierade som en faktor men vill konvertera den till en siffra. För att förhindra eventuell informationsförlust konverterar vi först till tecken och sedan till numeriskt:

years <- factor(2008:2012)

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

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

Om vi inte vill att LHS (vänster sida) används som det första argumentet på RHS (höger sida) finns det lösningar, till exempel att namnge argumenten eller använda . för att indikera var den rörliga ingången går.

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

Funktionella sekvenser

Med tanke på en sekvens av steg vi använder upprepade gånger är det ofta praktiskt att lagra det i en funktion. Rör gör det möjligt att spara sådana funktioner i ett läsbart format genom att starta en sekvens med en punkt som i:

. %>% RHS

Anta som exempel att vi har faktordatum och vill extrahera året:

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

Vi kan granska funktionens sammansättning genom att skriva dess namn eller använda functions :

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

Vi kan också komma åt varje funktion genom dess position i sekvensen:

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

I allmänhet kan denna metod vara användbar när tydlighet är viktigare än hastighet.

Uppdrag med% <>%

magrittr paketet innehåller en sammansatt tilldelningsinfix-operatör, %<>% , som uppdaterar ett värde genom att först leda det till ett eller flera rhs uttryck och sedan tilldela resultatet. Detta eliminerar behovet av att skriva ett objektnamn två gånger (en gång på varje sida av tilldelningsoperatören <- ). %<>% måste vara den första infix-operatören i en kedja:

library(magrittr)
library(dplyr)

df <- mtcars

Istället för att skriva

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

eller

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

Operatören av sammansatt tilldelning kommer både att röra och tilldela df :

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

Exponering av innehåll med% $%

Exponeringsrörsoperatören, %$% , exponerar kolumnnamnen som R-symboler i det vänstra objektet för högeruttrycket. Denna operatör är praktiskt när rörsystem i funktioner som inte har en data argument (till skillnad från, säg, lm ) och som inte tar en data.frame och kolumnnamn som argument (de flesta av de viktigaste dplyr funktioner).

Exponeringsrörsoperatören %$% tillåter en användare att undvika att bryta en pipeline när han behöver referera till kolumnnamn. Säg till exempel att du vill filtrera ett data.frame och sedan köra ett korrelationstest på två kolumner med 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

Här passerar standard %>% -röret data.frame genom att filter() , medan %$% -röret exponerar cor.test() för cor.test() .

Exponeringsröret fungerar som en rörledningsbar version av basen R with() -funktioner, och samma objekt på vänster sida accepteras som ingångar.

Använd röret med dplyr och ggplot2

Operatören %>% kan också användas för att leda dplyr-utgången till ggplot. Detta skapar en enhetlig EDA-pipeline som är lätt att anpassa. Denna metod är snabbare än att göra aggregeringar internt i ggplot och har den extra fördelen att undvika onödiga mellanvariabler.

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

Skapa biverkningar med% T>%

Vissa funktioner i R ger en bieffekt (dvs. spara, skriva ut, plotta, etc.) och ger inte alltid ett meningsfullt eller önskat värde.

%T>% (tee-operatör) låter dig vidarebefordra ett värde till en sidoeffekt-producerande funktion och samtidigt hålla det ursprungliga lhs värdet intakt. Med andra ord: tee-operatören fungerar som %>% , förutom att lhs är lhs själv, och inte resultatet av rhs funktionen / uttrycket.

Exempel: Skapa, rör, skriva och returnera ett objekt. Om %>% användes i stället för %T>% i detta exempel, skulle variabeln all_letters innehålla NULL snarare än värdet på det sorterade objektet.

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

Varning: Pipning av ett namn som inte heter för att save() ger ett namn som heter . när den laddas i arbetsområdet med load() . En lösning med hjälp av en hjälpfunktion är dock möjlig (som också kan skrivas inline som en anonym funktion).

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow