Dplyr group_by суммирует значение min / max для каждого столбца в группе, в зависимости от суффикса столбца - PullRequest
1 голос
/ 13 июня 2019

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

Например, дано:

set.seed(1)
dat <- data.frame(grp = c('A', 'A', 'B', 'B'), 
                  v1_high = rnorm(4), 
                  v2_high = rnorm(4), 
                  v3_low = rnorm(4))
# original
   grp    v1_high    v2_high     v3_low
 1   A -0.6264538  0.3295078  0.5757814
 2   A  0.1836433 -0.8204684 -0.3053884
 3   B -0.8356286  0.4874291  1.5117812
 4   B  1.5952808  0.7383247  0.3898432

Я хотел бы сгенерировать новый фрейм данных с двумя записями, соответствующими группам "A" и "B", с максимальными значениями каждого столбца, заканчивающимися на _high, и минимальными значениями каждого столбца, заканчивающимися на _low.

В этом случае:

# desired result
  grp   v1_high   v2_high     v3_low
1   A 0.1836433 0.3295078 -0.3053884
2   B 1.5952808 0.7383247  0.3898432

Наконец, число и имена таких столбцов заранее неизвестны.

В идеале суммирование также должно обрабатывать случай, когда отсутствуют столбцы _min и только столбцы _max, хотя я всегда могу проверить этот сценарий вручную и обработать два случая отдельно, используя if () { .. } заявление.

Есть предложения? Кажется, что это должно быть возможно с помощью функции sumrize_at () , но я не выяснил, как применять разные функции к различным наборам столбцов.

1 Ответ

1 голос
/ 13 июня 2019

Можно было бы сгруппировать по 'grp', получить max столбцов, которые заканчиваются на 'high' (имена столбцов), использовать это также как столбец группировки и получить min столбцов, которые заканчиваются на 'low '

library(dplyr)    
dat %>%
   group_by(grp) %>%  
   mutate_at(vars(ends_with('high')), max) %>% 
   group_by_at(vars(ends_with('high')), .add = TRUE) %>% 
   summarise_at(vars(ends_with('low')), min)
# A tibble: 2 x 4
# Groups:   grp, v1_high [2]
#  grp   v1_high v2_high v3_low
#  <fct>   <dbl>   <dbl>  <dbl>
#1 A       0.184   0.330 -0.305
#2 B       1.60    0.738  0.390

Это также будет работать, если нет min столбцов

dat[-4] %>%
    group_by(grp) %>%  
    mutate_at(vars(ends_with('high')), max) %>% 
    group_by_at(vars(ends_with('high')), .add = TRUE) %>%   
    summarise_at(vars(ends_with('low')), min)
# A tibble: 2 x 3
# Groups:   grp, v1_high [2]
#  grp   v1_high v2_high
#  <fct>   <dbl>   <dbl>
#1 A       0.184   0.330
#2 B       1.60    0.738

или другой параметр map2

library(purrr)
map2(list(min, max), list('low', 'high'), ~ 
      dat %>% 
         select(grp, ends_with(.y)) %>%
         group_by(grp) %>%
         summarise_all(.x)) %>% 
         reduce(inner_join, by = 'grp')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...