Get second to last input from %>% pipe operator

Viewed 112

I would like to make a factor out of a column I have just created within a pipeline. I can do this with the following code:

library("dplyr")
library("magrittr")
library("janitor")

iris <- iris %>% janitor::clean_names()    
iris %>% filter(species %in% c("setosa","versicolor")) %>% group_by(species) %>% 
             summarise(mean_sepal_length = mean(sepal_length)) %>% ungroup() %>%
             mutate(species = factor(species, levels = (iris %>% group_by(species) %>%  #<- works but messy
                                                            summarise(mean_sepal_length = mean(sepal_width)) %>% 
                                                            ungroup() %>% arrange(mean_sepal_length) %$% species))) %>% 
                    arrange(species)

I was wondering if there is "cleaner" way of doing this. Some thing like:

iris %>% filter(species %in% c("setosa","versicolor")) %>% group_by(species) %>% 
     summarise(mean_sepal_length = mean(sepal_length)) %>% ungroup() %>%
     mutate(species = factor(species, levels = (. %>% arrange(mean_sepal_length) %$% species))) %>% 
            arrange(species)

Where . is the second to last argument instead of the last argument given to the pipe?

This throws up an error because the last argument to the pipe is the mutate statement:

Error: Problem with `mutate()` input `species`. x 'match' requires vector arguments i Input `species` is `factor(...)`.

I think this is fundamentally not how the pipe operator works so this might not be possible.

2 Answers

For the second option to work, we can wrap the . inside {}

library(dplyr)
library(magrittr)
iris %>% 
 filter(species %in% c("setosa","versicolor")) %>%
 group_by(species) %>% 
 summarise(mean_sepal_length = mean(sepal_length)) %>% 
 ungroup() %>%
 mutate(species = factor(species, 
      levels = ({.} %>%
                  arrange(mean_sepal_length) %$% species))) %>%
 arrange(species)
# A tibble: 2 x 2
#  species    mean_sepal_length
#  <fct>                  <dbl>
#1 setosa                  5.01
#2 versicolor              5.94

You can arrange the data based on mean_sepal_length and then assign factor levels based on their occurrence using unique.

library(dplyr)

iris %>% 
  filter(species %in% c("setosa","versicolor")) %>%
  group_by(species) %>% 
  summarise(mean_sepal_length = mean(sepal_length)) %>%
  arrange(mean_sepal_length) %>%
  mutate(species = factor(species, levels = unique(species)))

#  species    mean_sepal_length
#  <fct>                  <dbl>
#1 setosa                  5.01
#2 versicolor              5.94
Related