Получить предпоследний ввод от оператора %>% pipe

#r #dplyr #tidyverse #magrittr

#r #dplyr #tidyverse #magrittr

Вопрос:

Я хотел бы сделать коэффициент из столбца, который я только что создал внутри конвейера. Я могу сделать это с помощью следующего кода:

 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)
  

Мне было интересно, есть ли «более чистый» способ сделать это. Что-то вроде:

 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)
  

Где . находится предпоследний аргумент вместо последнего аргумента, переданного каналу?

Это выдает ошибку, поскольку последним аргументом канала является оператор mutate:

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

Я думаю, что это принципиально не так, как работает оператор pipe, поэтому это может быть невозможно.

Комментарии:

1. непроизвольная реакция на использование janitor::clean_names(). Отредактированный пост для наглядности.

Ответ №1:

Чтобы второй вариант сработал, мы можем обернуть . внутри {}

 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
  

Комментарии:

1. Это здорово! Можете ли вы подробнее рассказать о том, что делает {.}? Извлекается ли он из предпоследнего аргумента? Было бы {{. }} извлекать с третьего по последний?

2. @daszlosek это данные, поступающие после метода summarise

3. @daszlosek если вы имели в виду исходную радужную оболочку данных, она недоступна на этом шаге

4. @daszlosek непонятно, зачем вам нужен factor шаг, iris %>% filter(species %in% c("setosa","versicolor")) %>% droplevels %>% group_by(species) %>% summarise(mean_sepal_length = mean(sepal_length)) %>% arrange(mean_sepal_length)

Ответ №2:

Вы можете arrange использовать данные на основе mean_sepal_length , а затем назначать factor уровни на основе их появления с помощью 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