Найдите максимальное значение одного столбца на основе group_by нескольких других столбцов

#r #dataframe #dplyr #group-by #data-cleaning

Вопрос:

У меня есть таблица следующего вида в R:

 | COUNTRY | date_start | code  | bin | ord |
| -----------------------------------------|
| Chile   | 04/11/2020 | 4.5.1 | 1   |  3  |
| Chile   | 04/11/2020 | 4.5.2 | 1   |  0  |   
| Norway  | 23/02/2021 | 4.4.1 | 1   |  2  |
| Norway  | 23/02/2021 | 4.4.2 | 0   |  1  |
| Norway  | 25/02/2021 | 4.4.2 | 0   |  1  |
 

Сначала я хочу удалить столбец «who_code», а затем я хочу создать дополнительный столбец «ordMax» и заполнить его максимальным значением столбца «ord» для данной «СТРАНЫ» и «даты начала». Таким образом, в этом примере новый столбец будет

 | COUNTRY | date_start | bin | ord | ordMax |
| ------------------------------------------|
| Chile   | 04/11/2020 | 1   |  3  |    3   |
| Chile   | 04/11/2020 | 1   |  0  |    3   |   
| Norway  | 23/02/2021 | 1   |  2  |    2   |
| Norway  | 23/02/2021 | 0   |  1  |    2   |
| Norway  | 25/02/2021 | 0   |  1  |    1   |
 

Я попробовал несколько методов в R, используя как «агрегат», так и библиотеку dplyr, но, похоже, ничего не сработало. Одна из вещей, которую я попробовал, была:

 df_k_reduced <- df_k %>%
  group_by(COUNTRY, date_start) %>%
  select(-code) %>%
  summarise(ordMax = max(ord))
 

Но это дает что-то вроде:

     | COUNTRY | date_start | ordMax |
    | ------------------------------|
    | Chile   | 04/11/2020 |    3   |   
    | Norway  | 23/02/2021 |    2   |
    | Norway  | 25/02/2021 |    1   |
 

Обратите внимание, что » bin «и исходный столбец» ord » также были удалены, хотя это не было первоначальным намерением.

Как бы я получил таблицу с этим дополнительным столбцом, где единственным удаляемым столбцом является «код», а строки не удаляются?

Ответ №1:

Мы можем использовать slice_max вместо summarise того, чтобы возвращать все столбцы после select шага

 library(dplyr)
df_k %>%
  group_by(COUNTRY, date_start) %>%
  select(-code) %>%
  slice_max(order_by = 'ord', n = 1)
 

Если нам нужно создать новый столбец, используйте mutate

 df_k %>%
    group_by(COUNTRY, date_start) %>%
    select(-code) %>%
    mutate(ordMax = max(ord, na.rm = TRUE)) %>%
    ungroup
 

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

1. Что делает этот метод, так это заменяет существующий столбец » ord » максимальными значениями. Можно ли сохранить исходный столбец «ord», поместив эти максимальные значения в новый столбец?

Ответ №2:

data.table путь

примеры данных

 library(data.table)
DT <- fread("COUNTRY | date_start | code  | bin | ord
  Chile   | 04/11/2020 | 4.5.1 | 1   |  3  
   Chile   | 04/11/2020 | 4.5.2 | 1   |  0     
   Norway  | 23/02/2021 | 4.4.1 | 1   |  2  
   Norway  | 23/02/2021 | 4.4.2 | 0   |  1  
   Norway  | 25/02/2021 | 4.4.2 | 0   |  1  ")
 

код

 DT[, ordMax := max(ord), by = .(COUNTRY, date_start)][, code := NULL][]
 

выход

 #    COUNTRY date_start bin ord ordMax
# 1:   Chile 04/11/2020   1   3      3
# 2:   Chile 04/11/2020   1   0      3
# 3:  Norway 23/02/2021   1   2      2
# 4:  Norway 23/02/2021   0   1      2
# 5:  Norway 25/02/2021   0   1      1
 

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

1. Звучит интересно. Я также должен добавить, что моя исходная таблица на самом деле намного больше и представляет собой существующий фрейм данных (который для этих целей я буду называть «df_k»). Я попробовал DT Что было бы эквивалентно чтению существующего фрейма данных? Сообщение об ошибке: ввод= должен содержать строку из одного символа, содержащую имя файла, системную команду, содержащую по крайней мере один пробел, URL-адрес, начинающийся с » http[s]://», «ftp[s]://» или » файл://», или сами входные данные, содержащие по крайней мере один n или r

2. data.table::setDT(df_k)

3. так library(data.table);setDT(df_k)[, ordMax := max(ord), by = .(COUNTRY, date_start)][, code := NULL][] что должно работать нормально.. (ПРИМЕЧАНИЕ: это навсегда изменит ваши df_k-данные!)

4. для преобразования обратно в data.frame используйте setDF()

5. Да, это сделало свое дело. Спасибо. Так что в основном я использовал DT