Группировать по относительной разнице в столбце (учитывая порядок упорядочения данных) - PullRequest
1 голос
/ 07 ноября 2019

У меня есть фрейм данных. Фрагмент:

df1 <- data.frame(x = c(1, 2, 1, 3, 5, 1, 4, 1), y = c(1, 1, 2, 2, 1, 1, 1, 3))
  x y
1 1 1
2 2 1
3 1 2
4 3 2
5 5 1
6 1 1
7 4 1
8 1 3

Мне нужно сгруппировать df1 по y и суммировать по x, но с учетом порядка y. Т.е. мне нужно создавать новые группы после каждого нового y и суммировать соответствующие x. Желаемый вывод:

   x y
1  3 1
2  4 2
3 10 1
4  1 3

Как это сделать в R?

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

Использование data.table:

library(data.table)

setDT(df1)[, .(x=sum(x), y=y[1]), .(rleid(y))][,rleid:=NULL][]

#>     x y
#> 1:  3 1
#> 2:  4 2
#> 3: 10 1
#> 4:  1 3

Или другое решение dplyr с использованием base::rle:

library(dplyr)

df1 %>% 
  group_by(y_grp = with(rle(y), rep(seq_along(lengths), lengths))) %>% 
  summarise(x = sum(x), y = y[1]) %>% 
  ungroup %>% select(-y_grp)

#> # A tibble: 4 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     3     1
#> 2     4     2
#> 3    10     1
#> 4     1     3
2 голосов
/ 07 ноября 2019

Мы можем использовать rleid (из data.table), чтобы получить идентификатор длины серии для группировки соседних похожих элементов и получить sum из 'x'

library(dplyr)
library(data.table)
df1 %>%
   group_by(grp= rleid(y), y) %>%
   summarise(x = sum(x)) %>%
   ungroup %>%
   select(names(df1))
# A tibble: 4 x 2
#      x     y
#  <dbl> <dbl>
#1     3     1
#2     4     2
#3    10     1
#4     1     3

Или только с dplyr, создайте логическое выражение со значениями lag 'y', преобразуйте в числовой индекс с cumsum в group_by и получите sum из 'x'

df1 %>%
   group_by(grp = cumsum(y != lag(y, default = first(y)))) %>% 
   summarise(x = sum(x), y = first(y)) %>%
   select(-grp)
...