Using rbind within a pipe

Viewed 133

Is it possible to use rbind within a pipe so that I don't have to define and store a variable to use it?

library(tidyverse)

## works fine
df <- iris %>% 
  group_by(Species) %>% 
  summarise(Avg.Sepal.Length = mean(Sepal.Length)) %>% 
  ungroup

df %>% 
  rbind(df)

## anyway to make this work?
iris %>% 
  group_by(Species) %>% 
  summarise(Avg.Sepal.Length = mean(Sepal.Length)) %>% 
  ungroup %>%
  rbind(.)
2 Answers

I don't know why you would want to rbind something with itself, but here you go:

iris %>% 
    group_by(Species) %>% 
    summarise(Avg.Sepal.Length = mean(Sepal.Length)) %>% 
    ungroup %>%
    rbind(., .)

Just to elaborate @MichaelDewar's answer, note the following section of ?magrittr::`%>%`:

Placing lhs elsewhere in rhs call

Often you will want lhs to the rhs call at another position than the first. For this purpose you can use the dot (.) as placeholder. For example, y %>% f(x, .) is equivalent to f(x, y) and z %>% f(x, y, arg = .) is equivalent to f(x, y, arg = z).

My understanding is that when . appears as an argument in the right hand side call, the left hand side is not inserted in the first position. The call is evaluated "as is", with . evaluating to the left hand side. Hence:

library("dplyr")
x <- data.frame(a = 1:2, b = 3:4)

x %>% rbind() # rbind(x)
##   a b
## 1 1 3
## 2 2 4

x %>% rbind(.) # same
##   a b
## 1 1 3
## 2 2 4

x %>% rbind(x) # rbind(x, x)
##   a b
## 1 1 3
## 2 2 4
## 3 1 3
## 4 2 4

x %>% rbind(x, .) # same
x %>% rbind(., x) # same
x %>% rbind(., .) # same
##   a b
## 1 1 3
## 2 2 4
## 3 1 3
## 4 2 4

You can devise clever tricks if you know the rules:

x %>% rbind((.)) # rbind(x, (x))
##   a b
## 1 1 3
## 2 2 4
## 3 1 3
## 4 2 4

(.) isn't parsed like ., so the left hand is inserted in the first position of the right hand side call. Compare:

as.list(quote(.))
## [[1]]
## .

as.list(quote((.)))
## [[1]]
## `(`
## 
## [[2]]
## .
Related