Упорядочите по убыванию на основе максимального значения группы, а затем удалите максимальный столбец в dplyr

#r #dplyr

Вопрос:

Предположим, что в iris наборе данных я хочу:

  • Порядок по Species на основе столбца , содержащего максимум Sepal.Length , в порядке убывания.
  • Удалите максимальный Sepal.Length столбец.
  • Внутри каждого Species , соблюдая порядок, начиная с первого шага выше, упорядочивайте Sepal.Length в порядке убывания.

Следующий код выдает желаемый результат:

 library(dplyr)  df lt;- iris %gt;%  group_by(Species) %gt;%  mutate(max.Sepal.length = max(Sepal.Length, na.rm = TRUE)) %gt;%  as.data.frame() %gt;%  arrange(desc(max.Sepal.length)) %gt;%  select(-max.Sepal.length)  df[,"Species"] lt;- factor(df[,"Species"],  levels = unique(df[,"Species"]),  ordered = TRUE)  df lt;- df %gt;%  arrange(Species, desc(Sepal.Length)) %gt;%  as.data.frame()  

Однако предположим вместо этого, что я хочу написать это как функцию:

 df_order lt;- function(df, group_col, value_col) {  df lt;- df %gt;%  group_by({{ group_col }}) %gt;%  mutate("max_{{value_col}}" := max({{value_col}}, na.rm = TRUE)) %gt;%  as.data.frame() %gt;%  arrange(desc("max_{{value_col}}")) %gt;%  select(-"max_{{value_col}}")    df[,"{{group_col}}"] lt;- factor(df[,"{{group_col}}"],  levels = unique(df[,"{{group_col}}"]),  ordered = TRUE)    df lt;- df %gt;%  arrange({{group_col}}, desc({{value_col}})) %gt;%  as.data.frame()  return(df) }  df_order(iris, Species, Sepal.Length)  

Увы, это не работает. Может ли кто-нибудь указать мне, где мой код неверен? Я не очень хорошо знаком с тем, как dplyr интегрировался с glue .

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

1. Вы можете использовать {{ внутренние dplyr функции, но не внутри простых базовых функций, таких как [ . Оставайтесь внутри dplyr и добавляйте свои новые столбцы с mutate помощью, а не df[, "{{group_col}}"] .

2. Кроме того, если вы хотите избавиться от группировки, ungroup() не используйте as.data.frame() ее .

3. @GregorThomas Спасибо. Однако при тестировании код не выполняет запланированное поведение, начиная с первой arrange() попытки. Вы знаете, почему это может быть?

4. Наконец, вам, вероятно , не нужен упорядоченный фактор. Все факторы имеют порядок для уровней. Вам действительно нужно только ordered = TRUE , если вы хотите определенный набор контрастов в модели, где 2-й уровень сравнивается с 1-м, 3-й-со 2-м и т. Д., Вместо обычного все уровни сравниваются с 1-м уровнем.

Ответ №1:

Вот один из способов исправить это — т. Е. Преобразовать string и использовать эту строку везде, где она нужна

 df_order lt;- function(df, group_col, value_col) {  value_col_str lt;- rlang::as_string(rlang::ensym(value_col))  group_col_str lt;- rlang::as_string(rlang::ensym(group_col))  df lt;- df %gt;%  group_by({{ group_col }}) %gt;%  mutate("max_{{value_col}}" := max({{value_col}}, na.rm = TRUE)) %gt;%  as.data.frame() %gt;%  arrange(desc(!! rlang::sym(glue::glue("max_{value_col_str}")))) %gt;%  select(-glue::glue("max_{value_col_str}"))    df[,group_col_str] lt;- factor(df[,group_col_str],  levels = unique(df[,group_col_str]),  ordered = TRUE)    df lt;- df %gt;%  arrange({{group_col}}, desc({{value_col}})) %gt;%  as.data.frame()  return(df)  }  

-тестирование

 out lt;- df_order(iris, Species, Sepal.Length)  Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 7.9 3.8 6.4 2.0 virginica 2 7.7 3.8 6.7 2.2 virginica 3 7.7 2.6 6.9 2.3 virginica 4 7.7 2.8 6.7 2.0 virginica 5 7.7 3.0 6.1 2.3 virginica 6 7.6 3.0 6.6 2.1 virginica 7 7.4 2.8 6.1 1.9 virginica 8 7.3 2.9 6.3 1.8 virginica ...  identical(out, df) [1] TRUE  

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

1. У меня складывается впечатление , что arrange() и select() не очень хорошо работает с конкатенацией имен столбцов и {{}} , и это {} (со строковым вводом) обычно предпочтительнее. Вы бы сказали, что это так?

2. @Clarinetist неясно, работает ли это в конкретной версии dplyr или нет. Но строковая версия должна работать в большинстве версий. Однако поведение функции tidyverse может меняться от версии к версии